Jak wykryć błędy przepełnienia pamięci w kodzie Arduino C.

10

Kilka razy miałem jakieś podejrzane dane wyjściowe na monitorze szeregowym po przesłaniu kodu do Arduino: jak wieczne wyjście białych znaków lub nagle odcięcie ciągów lub zakodowanych ciągów.

Ponieważ w Arduino IDE nie było błędu kompilacji ani ostrzeżenia, pomyślałem, że Arduino jest zepsute, ale po kilku testach odkryłem, że kompilator Arduino IDE nie przechwytuje wszystkich rodzajów błędów - szczególnie przy przypisywaniu zmiennych w pętli do struktur tablicowych. Wydaje się, że doprowadziło to do awarii Arduino w krótkim czasie.

Jak mogę wykryć błędy nie wyświetlane przez Arduino IDE?

powtac
źródło

Odpowiedzi:

10

Biblioteka MemoryFree może pomóc Ci znaleźć ryzyka z wykorzystaniem pamięci.

Przykład:

#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);
}

Nie jestem pewien, czy MemoryFree uwzględnia wskaźnik stosu. Jeśli wskaźnik stosu koliduje ze wskaźnikiem stosu, mogą wystąpić błędy segmentacji.


źródło
7

Najczęstszą przyczyną wyczerpania pamięci RAM jest użycie obiektu String lub użycie wielu tablic o stałych znakach (ciąg typu c).

Na przykład IDE 1.0.4 zawiera poprawkę do malloc, która nęka obiekt String od bardzo dawna.

Aby zmniejszyć ilość pamięci RAM zmarnowanej przez ciągi znaków o stałej długości, takie jak:

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

Możesz użyć makra F (). To makro zmusi tablicę znaków do pozostania w PROGMEM. Gdy używana jest tablica, zużywany jest tylko jeden bajt pamięci.

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

Należy pamiętać, że ciągów zapisanych w PROGMEM nie można zmienić w czasie wykonywania.

Jeśli chodzi o odkrycie, bez debugera lub kontrolera pamięci musisz użyć staromodnych technik detektywistycznych, aby znaleźć miejsce występowania problemów.

Baldengineer
źródło
1
Dziękuję za pomocną odpowiedź! Czy naprawdę nie ma debugera pamięci obsługującego IDE?
powtac
1
To stare pytanie, ale tak, istnieją odpowiednie debugery dla MCU atmel ATmega . Nie ma debugerów dla arduino , ponieważ łańcuch narzędzi arduino i „IDE” to w zasadzie zabawka.
Connor Wolf
1
Właściwie twoja wskazówka z F () zaoszczędziła nam około 100 bajtów w pamięci RAM!
powtac
1
Podczas używania F () pojawia się błąd kompilacji z ciągami zawierającymi //. :-(
powtac
Ten błąd kompilacji pojawia się w Arduino 1.5.7 ...
powtac
3

Wygląda na to, że mówisz o błędach środowiska wykonawczego (typu wyciek pamięci / segfault).

Nie ma żadnego sposobu na wykrycie takich błędów (chyba że bardzo starannie przeczesujesz kod) w kodzie, który jest już napisany. Jednak dość łatwo jest temu zapobiec podczas pisania kodu. Bądź bardzo ostrożny, pisząc pętle lub połączenia rekurencyjne; zadaj sobie pytanie „czy to wymknie się spod kontroli?”. Jeśli wygląda na to, że jest to pole do „wymknięcia się spod kontroli”, to napisz kod, aby się przed tym zabezpieczyć.

O segfaultach - po prostu sprawdź wartości brzegowe indeksów tablic i powinieneś być w porządku. Jeśli używasz wskaźników, bądź ostrożny z arytmetyką wskaźników.

Manishearth
źródło