¿Cómo descubrir errores de desbordamiento de memoria en el código Arduino C?

10

Varias veces tuve algunos resultados sospechosos en el Monitor de serie después de cargar el código al Arduino: como la salida eterna de espacios en blanco o de repente cortes de cadenas o cadenas codificadas.

Debido a que no hubo error de compilación o advertencia en el IDE de Arduino, pensé que el Arduino estaba roto, pero después de algunas pruebas descubrí que el compilador IDE de Arduino no detecta todo tipo de errores, especialmente al asignar variables en un bucle para estructuras de matriz. Esto parece bloquear el Arduino en un corto período de tiempo.

¿Cómo puedo descubrir errores que el IDE de Arduino no muestra?

Powtac
fuente

Respuestas:

10

La biblioteca MemoryFree puede ayudarlo a encontrar riesgos con el uso de la memoria.

Ejemplo:

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

No estoy seguro si MemoryFree representa el puntero de la pila. Si su puntero de pila choca con su puntero de pila, puede experimentar fallas de segmentación.


fuente
7

La causa más común de agotamiento de RAM es usar el objeto String o usar muchos arreglos de caracteres constantes (cadena de estilo c).

Por supuesto, IDE 1.0.4 incluye una solución a malloc que ha afectado al objeto String durante mucho tiempo.

Para reducir la RAM desperdiciada por cadenas de caracteres constantes como:

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

Puede usar la macro F (). Esta macro obligará a la matriz de caracteres a permanecer en PROGMEM. Cuando se usa la matriz, solo se consume un byte de memoria.

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

Tenga en cuenta que las cadenas almacenadas en PROGMEM no pueden modificarse durante el tiempo de ejecución.

En lo que respecta al descubrimiento, sin un depurador o controlador de memoria, debe usar técnicas de detective anticuadas para encontrar dónde ocurren los problemas.

Baldengineer
fuente
1
¡Gracias por la útil respuesta! ¿Realmente no hay un IDE compatible con el depurador de memoria?
powtac
1
Esta es una vieja pregunta, pero sí, hay depuradores adecuados para atmel ATmega MCU. No hay depuradores para arduinos , porque la cadena de herramientas arduino e "IDE" es básicamente un juguete.
Connor Wolf
1
En realidad, su pista con F () nos ahorró unos cientos de bytes en RAM.
powtac
1
Recibo un error de compilación cuando uso F () con cadenas que contienen //. :-(
powtac
Me sale este error de compilación en Arduino 1.5.7 ...
powtac
3

Parece que estás hablando de errores de tiempo de ejecución (del tipo de pérdida de memoria / segfault) aquí.

No hay forma de descubrir tales errores (a menos que peines con mucho cuidado a través del código) en el código que ya está escrito. Sin embargo, es bastante fácil evitar que esto suceda mientras se escribe el código. Solo tenga mucho cuidado al escribir bucles o llamadas recursivas; pregúntate "¿esto podría salirse de control?". Si parece que estas son posibilidades de que "se salga de control", escriba el código para protegerse contra eso.

Acerca de los valores predeterminados: solo verifique los valores límite de los índices de matriz y debería estar bien. Si está utilizando punteros, tenga cuidado con la aritmética de punteros.

Manishearth
fuente