Wie erkenne ich Speicherüberlauffehler im Arduino C-Code?

10

Mehrmals hatte ich einige verdächtige Ausgaben auf dem seriellen Monitor, nachdem ich Code auf das Arduino hochgeladen hatte: wie die ewige Ausgabe von Leerzeichen oder das plötzliche Ausschneiden von Zeichenfolgen oder verschlüsselten Zeichenfolgen.

Da es in der Arduino IDE keinen Kompilierungsfehler oder keine Warnung gab, dachte ich, das Arduino sei defekt, aber nach einigen Tests stellte ich fest, dass nicht alle Arten von Fehlern vom Arduino IDE-Compiler abgefangen werden - insbesondere beim Zuweisen von Variablen in einer Schleife für Array-Strukturen. Dies scheint den Arduino in kurzer Zeit zum Absturz zu bringen.

Wie kann ich Fehler erkennen, die von der Arduino IDE nicht angezeigt werden?

powtac
quelle

Antworten:

10

Die MemoryFree-Bibliothek kann Ihnen dabei helfen, Risiken bei der Speichernutzung zu finden.

Beispiel:

#include <MemoryFree.h>

// On Arduino Duemilanove with ATmega328:
//
// Reported free memory with str commented out:
// 1824 bytes
//
// Reported free memory with str and Serial.println(str) uncommented:
// 1810
//
// Difference: 14 bytes (13 ascii chars + null terminator)

// 14-bytes string
//char str[] = "Hello, world!";


void setup() {
    Serial.begin(115200);
}


void loop() {
    //Serial.println(str);

    Serial.print("freeMemory()=");
    Serial.println(freeMemory());

    delay(1000);
}

Ich bin nicht sicher, ob MemoryFree den Stapelzeiger berücksichtigt. Wenn Ihr Stapelzeiger mit Ihrem Heap-Zeiger kollidiert, können Segmentierungsfehler auftreten.


quelle
7

Die häufigste Ursache für RAM-Erschöpfung ist die Verwendung des String-Objekts oder die Verwendung vieler Arrays mit konstanten Zeichen (Zeichenfolge im C-Stil).

Forutant enthält IDE 1.0.4 einen Fix für Malloc, der das String-Objekt sehr lange geplagt hat.

So reduzieren Sie den durch Konstantzeichenfolgen verschwendeten Arbeitsspeicher wie:

Serial.print("Hello World");  // This consumes RAM!

Sie können das Makro F () verwenden. Dieses Makro zwingt das Zeichenarray, in PROGMEM zu bleiben. Wenn das Array verwendet wird, wird nur ein Byte Speicher belegt.

Serial.print(F("Hello World"));  // Keeps the character-array in PROGMEM

Beachten Sie, dass in PROGMEM gespeicherte Zeichenfolgen zur Laufzeit nicht geändert werden können.

Bei der Ermittlung müssen Sie ohne Debugger oder Speichercontroller altmodische Detektivtechniken verwenden, um herauszufinden, wo die Probleme auftreten.

Baldengineer
quelle
1
Vielen Dank für die hilfreiche Antwort! Es gibt wirklich keinen IDE-Support-Speicher-Debugger?
Powtac
1
Dies ist eine alte Frage, aber ja, es gibt richtige Debugger für ATMEL-ATMega- MCUs. Es gibt keine Debugger für Arduinos , da die Arduino-Toolchain und "IDE" im Grunde ein Spielzeug sind.
Connor Wolf
1
Tatsächlich hat uns Ihr Hinweis mit F () einige hundert Bytes im RAM gespart!
Powtac
1
Ich erhalte einen Kompilierungsfehler, wenn ich F () mit Zeichenfolgen verwende, die enthalten //. :-(
powtac
Ich bekomme diesen Kompilierungsfehler auf Arduino 1.5.7 ...
powtac
3

Sieht so aus, als würden Sie hier von Laufzeitfehlern (vom Typ Speicherverlust / Segfault) sprechen.

Es gibt keine Möglichkeit, solche Fehler in bereits geschriebenem Code zu entdecken (es sei denn, Sie kämmen den Code sehr sorgfältig durch). Es ist jedoch recht einfach zu verhindern, dass diese beim Schreiben des Codes auftreten. Seien Sie nur sehr vorsichtig, wenn Sie Schleifen oder rekursive Aufrufe schreiben. Fragen Sie sich "könnte dies außer Kontrolle geraten?". Wenn es so aussieht, als ob dies Spielraum für "außer Kontrolle geraten" ist, schreiben Sie Code, um sich davor zu schützen.

Über Segfaults - überprüfen Sie einfach die Grenzwerte der Array-Indizes und Sie sollten in Ordnung sein. Wenn Sie Zeiger verwenden, gehen Sie bitte vorsichtig mit der Zeigerarithmetik um.

Manishearth
quelle