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;
该结构有两个char指针,使用时,使用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文件系统数据),还使用封装运行时的外部shell进程,每秒为我提供内存性能数据。注意:问题是在没有监控的情况下发生的,所以我知道它不会影响结果。
现在,我想释放一切:
// 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()发生了,因为新分配的连续内存不可用。
响应这个问题涉及(a)初始化我的结构大小以容纳一个n个元素块(n为40到100,具体取决于需要); (b)当结构需要增长时(我们用完了初始分配)我复制原始结构,完全释放原始结构,然后分配一个大小为n + increment_size的新结构,然后从中初始化新结构老了,然后老了。在新记录请求在分配计数范围内的情况下,我的所有功能都返回当前分配编号。
新方案根本不使用realloc()。鉴于这个问题,我认为这是一个加号。
复杂,在某些情况下可能会很慢,但至少记忆似乎已经得到控制。
答案 0 :(得分:1)
使用free
或realloc
释放内存并不意味着将其返回给系统。堆机器只会将这些页面保留在某个位置,以便将它们用于下一次分配。如果你真的想知道你是否正确释放所有内存,请使用像valgrind这样的工具。这将告诉您“postmortem”,如果您的进程释放了它分配的所有内存,或者如果没有,它将指向您的代码中的位置,这些位置在之后不会释放而分配。