gpt4 book ai didi

c - 释放动态结构不会释放内存

转载 作者:行者123 更新时间:2023-11-30 16:00:48 25 4
gpt4 key购买 nike

    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 个元素的 block (n 为 40 到 100,具体取决于需要); (b) 当结构需要增长时(我们用完了初始分配),我复制原始结构,完全释放原始结构,然后分配一个大小为 n +increment_size 的新结构,然后从旧的,然后释放旧的。如果新记录请求在分配计数内,我的函数所做的就是返回当前分配编号。

新方案根本不使用realloc()。考虑到这个问题,我认为这是一个优点。

很复杂,在某些情况下可能会很慢,但至少内存似乎受到了控制。

最佳答案

使用freerealloc释放内存并不意味着它会返回给系统。堆机制只会将这些页面保留在某个地方,以便它们可用于下一次分配。如果您确实想知道是否正确释放了所有内存,请使用 valgrind 这样的工具。这将告诉您“事后分析”,您的进程是否释放了它分配的所有内存,否则它将指向您代码中分配但随后不释放的位置。

关于c - 释放动态结构不会释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7420218/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com