Массив строк не освобождается при выходе из области - PullRequest
11 голосов
/ 16 января 2012

Я сталкиваюсь с некоторыми серьезными утечками памяти в моем приложении, поэтому я настроил это чрезвычайно простое решение, чтобы проверить, что происходит, когда массив String выходит из области видимости ...

Я знаю, что старая реализация TextStringof String отсутствовал деструктор, но, похоже, в текущей реализации он есть.

Я использую эту библиотеку MemoryFree ( Обратите внимание, что этот связанный код теперь исправлен на основе принятогоответ на этот вопрос ).

В коде рассматриваются два сценария: выделение массива char и массива строк в двух разных функциях для принудительного выхода из области видимости в обоих случаях.

#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 */ }

Вывод:

CHAR *: до 1710 года, после 1710 года, разница 0STRING: до 1645 года, после 1309 года, Diff 336

Почему выделение массива String не стирается из памяти?

Ответы [ 3 ]

4 голосов
/ 16 января 2012

Я столкнулся с проблемами обработки памяти в версиях Arduino до 1.0 при тестировании класса String ( см. Сообщение на форуме здесь ).

Конструктор String внутренне использует reallocи именно эта (avr libc) обработка динамической памяти вызывала проблемы (из-за того, что указатель на вершину кучи __brkval не обновлялся при free()).

Запустите следующий код, чтобы увидетьэти проблемы в версиях 0023, 0022 и т. д. В Arduino 1.0 в коде не должно быть утечек памяти:

#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() {
}

Кроме того, используемая вами библиотека MemoryFree может давать неправильные результаты, поскольку она не учитываетаккаунт свободный список.Попробуйте эту обновленную версию 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 голосов
/ 16 января 2012

Закомментируйте строку String s[100]; и посмотрите, получите ли вы другие результаты. Похоже, что выделение памяти, которое вы видите, связано с строковыми операциями в вашей функции setup(), а не с объявлением локального массива строк в AllocateStrArr(). Вы можете взглянуть на WString.cpp и WString.h , чтобы увидеть, что operator+ был переопределен, поэтому каждый вызов String() или конкатенация с использованием + может создать другой объект.

0 голосов
/ 16 января 2012

Если вы посмотрите на источник Arduino , вы можете встретить файл ". \ Arduino-1.0 \ hardware \ arduino \ cores \ arduino \ WString.cpp".В этом файле я заметил, что String не имеет конструктора по умолчанию (без параметров).Возможно это могло быть проблемой?Сомнительно, но в любом случае источник должен помочь.Желаем удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...