Comment découvrir les erreurs de débordement de mémoire dans le code Arduino C?

10

Plusieurs fois, j'ai eu des sorties suspectes sur le moniteur série après avoir téléchargé du code sur l'Arduino: comme une sortie éternelle d'espaces blancs ou une coupure soudaine de chaînes ou des chaînes brouillées.

Parce qu'il n'y avait pas d'erreur de compilation ou d'avertissement dans l'IDE Arduino, je pensais que l'Arduino était cassé mais après quelques tests, j'ai découvert que toutes sortes d'erreurs n'étaient pas détectées par le compilateur IDE Arduino - en particulier lors de l'attribution de variables dans une boucle pour les structures de tableau. Cela semble faire planter l'Arduino en peu de temps.

Comment puis-je découvrir des erreurs non affichées par l'IDE Arduino?

powtac
la source

Réponses:

10

La bibliothèque MemoryFree peut vous aider à identifier les risques liés à l'utilisation de la mémoire.

Exemple:

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

Je ne sais pas si MemoryFree représente le pointeur de pile. Si votre pointeur de pile entre en collision avec votre pointeur de tas, vous pouvez rencontrer des erreurs de segmentation.


la source
7

La cause la plus courante d'épuisement de la RAM est l'utilisation de l'objet String ou l'utilisation de nombreux tableaux de caractères constants (chaîne de style c).

Forutantly IDE 1.0.4 inclut un correctif pour malloc qui tourmente l'objet String depuis très longtemps.

Pour réduire la RAM gaspillée par des chaînes de caractères constants comme:

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

Vous pouvez utiliser la macro F (). Cette macro forcera le tableau de caractères à rester dans PROGMEM. Lorsque la baie est utilisée, un seul octet de mémoire est consommé.

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

Gardez à l'esprit que les chaînes stockées dans PROGMEM ne peuvent pas être modifiées pendant l'exécution.

En ce qui concerne la découverte, sans débogueur ou contrôleur de mémoire, vous devez utiliser des techniques de détective à l'ancienne pour trouver où les problèmes se produisent.

baldengineer
la source
1
Merci pour la réponse utile! Il n'y a vraiment pas de débogueur de mémoire de support IDE?
powtac
1
C'est une vieille question, mais oui, il existe des débogueurs appropriés pour les microcontrôleurs atmel ATmega . Il n'y a pas de débogueur pour Arduinos , car la chaîne d'outils Arduino et "IDE" est fondamentalement un jouet.
Connor Wolf
1
En fait, votre indice avec F () nous a fait économiser quelques centaines d'octets en RAM!
powtac
1
J'obtiens une erreur de compilation lors de l'utilisation de F () avec des chaînes qui contiennent //. :-(
powtac
J'obtiens
3

On dirait que vous parlez ici d'erreurs d'exécution (du type fuite de mémoire / erreur de segmentation).

Il n'y a aucun moyen de découvrir de telles erreurs (sauf si vous peignez très soigneusement le code) dans du code déjà écrit. Cependant, il est assez facile d'empêcher que cela ne se produise lors de l' écriture du code. Soyez très prudent lorsque vous écrivez des boucles ou des appels récursifs; demandez-vous "est-ce que cela pourrait devenir incontrôlable?". S'il semble que ce soit la possibilité pour lui de "devenir incontrôlable", alors écrivez du code pour vous protéger contre cela.

À propos de segfaults - vérifiez simplement les valeurs limites des indices de tableau et vous devriez être OK. Si vous utilisez des pointeurs, faites attention à l'arithmétique des pointeurs.

Manishearth
la source