2012-01-15 7 views
11

estoy corriendo en algunos graves pérdidas de memoria en mi solicitud, por lo que esta configuración solución extremadamente desnuda para probar lo que sucede cuando una matriz de cadenas se sale del ámbito ...array Alfa no cancela la asignación al salir alcance

que sé que la antigua implementación TextString de String carecía de un destructor, pero esta implementación actual parece tenerlo.

Estoy usando this MemoryFree library (Tenga en cuenta que este código vinculado se ha solucionado en función de la respuesta aceptada a esta pregunta).

El código examina dos escenarios: Asignación de matriz de caracteres y matriz de cadenas en dos funciones diferentes para forzar la salida del ámbito en ambas.

#include <MemoryFree.h> 

void setup() { 
    // put your setup code here, to run once: 
    Serial.begin(9600); 
    int freeBefore, freeAfter; 

    //TEST ALLOCATION OF CHAR ARRAY// 
    freeBefore = freeMemory(); 
    AllocateCharArr(); 
    freeAfter = freeMemory(); 
    Serial.println("CHAR*: Before " + String(freeBefore) 
    + ", After " + String(freeAfter) 
    + ", Diff " + String(freeBefore - freeAfter)); 

    //TEST ALLOCATION OF STRING// 
    freeBefore = freeMemory(); 
    AllocateStringArr(); 
    freeAfter = freeMemory(); 
    Serial.println("STRING: Before " + String(freeBefore) 
    + ", After " + String(freeAfter) 
    + ", Diff " + String(freeBefore - freeAfter)); 
} 

void AllocateCharArr() { 
    char s[100]; 
} 

void AllocateStringArr() { 
    String s[100]; 
} 

void loop() { /* empty */ } 

Salida:

char *: Antes de 1710, después de 1710, Dif 0
cadena: Antes de 1645, después de 1309, Dif 336

¿Cómo es que la asignación String gama no se borró de la memoria?

+1

¿Cuál es el resultado cuando el array 'string' es mucho más pequeñas (por ejemplo, 10 elementos)? – ouah

+0

Interesante: 50 elementos = diff 136, 25 elementos = diff 36, 10 elementos = diff 0 –

+0

¿Qué versión del software Arduino está usando (0023, 1.0, ...)? –

Respuesta

4

He encontrado problemas de manejo de memoria en las versiones de Arduino anteriores a la 1.0 al probar la clase String (see forum post here).

La cadena de constructor utiliza realloc internamente y es esta (avr libc) dinámica de manejo de la memoria que estaba causando los problemas (debido al puntero a la parte superior de la pila __brkval no está actualizado sobre free()).

ejecute el código siguiente para ver estos temas en las versiones 0023, 0022, etc. En Arduino 1.0 el código no deberá presentar fugas de memoria:

#if (ARDUINO >= 100) 
#include <Arduino.h> 
#else 
#include <WProgram.h> 
#endif 
#include <HardwareSerial.h> 
#include <MemoryFree.h> 

void setup() { 
    // put your setup code here, to run once: 
    Serial.begin(9600); 
    int freeBefore, freeAfter; 

    freeBefore = freeMemory(); 

    void* buffer = malloc(10); 
    if (buffer == 0) { 
    Serial.println("Failed to allocate memory"); 
    } 
    free(buffer); 

    freeAfter = freeMemory(); 
    Serial.println("Before " + String(freeBefore) 
    + ", After " + String(freeAfter) 
    + ", Diff " + String(freeBefore - freeAfter)); 
} 

void loop() { 
} 

Además, la biblioteca MemoryFree que está utilizando puede dar mal resultados ya que no tiene en cuenta la lista gratuita. Prueba esta versión actualizada MemoryFree.cpp:

extern unsigned int __heap_start; 
extern void *__brkval; 

/* 
* The free list structure as maintained by the 
* avr-libc memory allocation routines. 
*/ 
struct __freelist { 
    size_t sz; 
    struct __freelist *nx; 
}; 

/* The head of the free list structure */ 
extern struct __freelist *__flp; 

#include "MemoryFree.h"; 

/* Calculates the size of the free list */ 
int freeListSize() { 
    struct __freelist* current; 
    int total = 0; 

    for (current = __flp; current; current = current->nx) { 
    total += 2; /* Add two bytes for the memory block's header */ 
    total += (int) current->sz; 
    } 

    return total; 
} 

int freeMemory() { 
    int free_memory; 

    if ((int)__brkval == 0) { 
    free_memory = ((int)&free_memory) - ((int)&__heap_start); 
    } else { 
    free_memory = ((int)&free_memory) - ((int)__brkval); 
    free_memory += freeListSize(); 
    } 
    return free_memory; 
} 
+0

¡Gracias! Resultó que era la función freeMemory la que informaba los valores incorrectos. En su lugar, utilizando el método suministrado, da resultados correctos y no parece que se produzca ninguna fuga. –

+0

Es bueno saber que las bibliotecas Arduino 1.0 están bien. Actualizará la respuesta. ¡Gracias! –

+0

He actualizado el código de la biblioteca MemoryFree.cpp en el sitio Arduino (http://arduino.cc/playground/Code/AvailableMemory) en línea con esta respuesta aceptada. –

0

Si mira a través del Arduino source, puede encontrar el archivo ". \ Arduino-1.0 \ hardware \ arduino \ cores \ arduino \ WString.cpp". En este archivo, noté que String no tiene un constructor predeterminado (sin parámetros). Quizás este podría ser el problema? Dudoso, pero de todos modos, la fuente debería ayudar. La mejor de las suertes.

+0

He estado investigando ese archivo ya, principalmente para verificar que tenía un destructor. Voy a probar para ver si una matriz inicializada con valores hace alguna diferencia. –

0

Comente la línea String s[100]; y vea si obtiene resultados diferentes. Parece que las asignaciones de memoria que está viendo se deben a las operaciones de cadena en su función setup(), no a la declaración de una matriz local de cadenas en AllocateStrArr(). Puede echar un vistazo a WString.cpp y WString.h para ver que operator+ ha sido anulado, por lo que cada llamada a String() o concatenación usando + podría crear otro objeto.

+0

Comentando que la línea trae su diff 0. –

Cuestiones relacionadas