释放动态结构不释放内存

时间:2011-09-14 17:08:24

标签: c

    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()。鉴于这个问题,我认为这是一个加号。

复杂,在某些情况下可能会很慢,但至少记忆似乎已经得到控制。

1 个答案:

答案 0 :(得分:1)

使用freerealloc释放内存并不意味着将其返回给系统。堆机器只会将这些页面保留在某个位置,以便将它们用于下一次分配。如果你真的想知道你是否正确释放所有内存,请使用像valgrind这样的工具。这将告诉您“postmortem”,如果您的进程释放了它分配的所有内存,或者如果没有,它将指向您的代码中的位置,这些位置在之后不会释放而分配。