将动态分配的内存返回给操作系统而不终止程序

时间:2014-03-11 10:31:39

标签: c++ linux memory-management malloc free

我正在开发一个程序,我正在使用大量但内存有限的程序。在不同的线程上运行时分配和释放内存。但是,我注意到程序的内存使用量不会保持在指定的范围内。它会随着时间的推移而增加。我编写了以下示例程序来检查内存是否正被释放回操作系统。已释放一半已分配的内存以检查内存使用率是否下降。

int main()
{
    char *p[COUNT];

    for(int i = 0; i < COUNT; i++)
    {
        p[i] = new char[1048576];
        memset (p[i], 0, 1048576);
        printf("%p\n", p[i]);
    }

    printf("done allocating ... \n");

    sleep(10);

    printf("Freeing\n");
    for(int i; i < COUNT; i++)
    {
        delete[] p[i];
    }

    while(1)
        sleep(1);
}

运行程序后,操作系统似乎无法回收已释放的页面。在分配和释放后,内存使用情况与linux中的“top”命令中看到的相同。它只是将页面标记为可由同一程序重用。 在我的程序中,malloc和free在不同的线程上运行。当malloc被调用的频率高于free并且进程数据段变得非常大,导致OS将页面交换到磁盘时,这会造成内存管理问题。这使得程序和操作系统变得缓慢且无响应。操作系统有什么方法可以回收释放的内存吗?

2 个答案:

答案 0 :(得分:2)

在Linux上,您可能会获得virtual memory mmap(2)malloc::operator new等使用的空间proc(5))。然后您可以使用munmap

稍后发布

由于mmapmunmap在某种程度上很昂贵,malloc(因此::operator new通常在malloc之上实现)尝试重复使用free -d内存区域,所以不要总是将内存释放到内核(低于一个很大的阈值,可能是128K或更高)。

BTW,Advanced Linux Programming为内核提供了一个有用的界面来查询事物。对于pid 1234的过程,您可以cat /proc/1234/maps显示其地址空间内存映射(从您的流程内部,使用/proc/self/maps

所以你可以编码:

const size_t sz = 1048576;
/// allocating loop
for (i=0; i < 2000 ;i++ ) {
  void* ad = mmap(NULL, sz, PROT_READ|PROT_WRITE, 
                  MMAP_PRIVATE|MMAP_ANONYMOUS,
                  -1, (off_t)0);
  if (ad == MMAP_FAILED)
    { perror("mmap"); exit (EXIT_FAILURE); }
  p[i] = ad;
  memset (p[i], 0, sz); // actually uneeded
}
printf ("done allocating ... \n");
sleep(5);
// freeing loop
printf("Freeing\n");
for (i=0; i < 2000 ;i++ ) {
  if (munmap((void*)p[i], sz)) 
    { perror("munmap"); exit(EXIT_FAILURE); }
  p[i] = nullptr;
}

请注意,mmap MAP_ANONYMOUS成功归零内存区域,因此您无需memset清除它。

在C ++中,您还可以定义自己的operator new(调用mmap)和operator delete (如果需要,请致电munmap)。

另请阅读{{3}}。

答案 1 :(得分:2)

进程退出后,将回收进程使用的所有内存。操作系统可以保持推测性缓存数据,以防万一(如Linux Ate My RAM中所述)。只要另一个进程需要,就会释放内存。

编辑:因为你的意思是一个长时间运行的服务器进程,所以你关心的是内存使用,而进程仍在运行。我可以建议valgrind作为检测应用程序内存泄漏的工具,并RAII作为防止内存泄漏的编码技术。小心Linux(通常!)上的内存使用很难测量/解释,像ps和top这样的工具的输出可能会产生误导和不直观,例如:根据{{​​3}}。