Environment: uname -a: 2.6.38 #18 Thu Apr 28 12:38:48 CEST 2011 armv5tejl GNU/Linux
GCC:
gcc -v
Using built-in specs.
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-sjlj-exceptions --enable-checking=release --build=arm-linux-gnueabi --host=arm-linux-gnueabi --target=arm-linux-gnueabi
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)
В приведенном ниже коде я, кажется, все делаю правильно, но выделенная память явно не освобождается.Мой метод структуры не является связанным списком.
Я говорю «очевидно», понимая, что сборщик мусора будет действовать в любое время, когда пожелает.Тем не менее, поскольку я вижу, что RSS увеличивается постепенно, когда мой тестовый код выполняется, и поскольку он выделяет одинаковое количество места в каждом тесте, я должен подумать, что распределение будет использовано повторно.
Мой код реализует простойдинамическая структура:
struct _aemErrors
{
int stored; // true = stored to sql
int mailed; // true = mailed to alert
int nType; // LOG_DEBUG LOG_INFO...
int time; // error triggered timestamp
int line; // line in file that triggered
char *cFunction; // function that triggered
char *cDesc; // description of problem
};
struct _aemErrors **aemErrors;
int aemErrorsCount;
Структура имеет два указателя на символы, которые, при использовании, создаются с помощью malloc () или strdup ()
Каждая запись структуры инициализируется следующим образом:
int AddaemError(void)
{
++aemErrorsCount;
aemErrors = (struct _aemErrors **)realloc(aemErrors, (aemErrorsCount+1) * sizeof(struct _aemErrors *));
aemErrors[aemErrorsCount] = (struct _aemErrors *)malloc(sizeof(struct _aemErrors));
return(aemErrorsCount);
}
Итак:
int main(int argc,char **argv)
{
// initialize the structure
aemErrors=NULL;
aemErrorsCount=-1;
int nPtr=0;
int nLoopCount=0;
while (nLoopCount<100)
{
for (nPtr=0;nPtr<1000;nPtr++)
{
nPtr=AddaemError();
aemErrors[nPtr]->stored=false;
aemErrors[nPtr]->mailed=false;
aemErrors[nPtr]->nType=LOG_ALERT;
aemErrors[nPtr]->nTime=time(NULL);
aemErrors[nPtr]->line=0;
aemErrors[nPtr]->cFunction=strdup("ThisIsATest");
aemErrors[nPtr]->cDesc=strdup("ThisIsATest");
}
FreeaemErrors();
sleep(5);
++nLoopCount;
}
return(0);
}
По мере вращения цикла я вижу, как RSS растет соответствующим образом.Я использую тестер состояния внутренней памяти (не показан: читает данные файловой системы proc), а также использую процесс внешней оболочки, который инкапсулирует среду выполнения и дает мне данные о производительности памяти каждую секунду.Примечание: проблема возникает без мониторинга, поэтому я знаю, что это не влияет на результат.
Теперь я хочу освободить все:
// cleanup the dynamic structure
int FreeaemErrors(void)
{
if (aemErrors==NULL)
return(true);
int i=0;
printf("FreeaemErrors():Count=%i\n",aemErrorsCount);
for(i = 0; i <= aemErrorsCount; i++)
{
free(aemErrors[i]->cFunction);
free(aemErrors[i]->cDesc);
free(aemErrors[i]);
aemErrors[i]->cFunction=NULL;
aemErrors[i]->cDesc=NULL;
aemErrors[i]=NULL;
}
printf("Done. Free root\n");
free(aemErrors);
aemErrors=NULL;
aemErrorsCount=-1;
printf("Returning\n");
return(true);
}
Поэтому я запускаю FreeaemErrors ();а затем подождите несколько секунд, наблюдая за памятью.Он не уменьшается.
И в следующий раз, когда я запускаю цикл заполнения, добавляя еще 1000 записей к предположительно чистой структуре, RSS снова поднимается.
В настоящий момент я несколько озадачен.
Идеи, кто-нибудь?
Спасибо за ваш вклад здесь.
После довольно большого тестирования с различными размерами конструкции, я обнаружил, что как только мы достигаем определенногоразмер, а затем все бесплатно, RSS возвращается почти туда, где я ожидал.Но не совсем.
Я узнал немного больше о фрагментации памяти и о том, как программа может раздуться, когда, как в моем примере, происходит realloc (), потому что смежная память для нового выделения недоступна.
Реагирование на эту проблему включало (а) инициализацию размера моей структуры для хранения блока из n элементов (от 40 до 100, в зависимости от потребностей);(б) когда структура должна расти (у нас закончилось начальное распределение), я делаю копию исходной структуры, полностью освобождаю исходную, затем выделяю новую с размером n + increment_size, затем инициализирую новую изстарый, то освободи старый.В случае, когда новый запрос записи находится в пределах количества выделений, моя функция возвращает текущий номер выделения.
Новая схема вообще не использует realloc ().Учитывая проблему, я считаю это плюсом.
Сложно, и, возможно, в некоторых случаях оно будет медленным, но, по крайней мере, память проверяется.