在C ++中,即使调用了delete,进程何时保留已分配的内存?

时间:2009-08-11 10:53:50

标签: c++ memory gcc memory-management

我想了解GCC运行时在以下情况下发生了什么。

我有一个C ++程序,它分配许多内存块然后删除它们。令人费解的是,GCC运行时没有将内存返回给操作系统。相反,它仍然由我的程序保存,我假设我想在不久的将来分配类似的内存块。

以下程序演示了会发生什么:

#include <iostream>
using namespace std;

void pause1()
{
    cout << "press any key and enter to continue";
    char ch;
    cin >> ch;
}

void allocate(int size)
{
    int **array = new int*[size];
    for (int c = 0; c < size; c++) {
        array[c] = new int;
    }
    cout << "after allocation of " << size << endl;
    for (int c = 0; c < size; c++) {
        delete array[c];
    }
    delete [] array;
}

int main() {
    cout << "at start" << endl;
    pause1();
    int size = 1000000;
    for (int i = 0; i < 3; i++) {
        allocate(size);
        cout << "after free" << endl;
        pause1();
        size *= 2;
    }
    return 0;
}

我通过运行“ps -e -o vsz,cmd”来检查每次暂停时进程占用的内存量(根本不应该保留任何内存)。

每次暂停时进程持有的金额如下:

  2648kb - at start  
 18356kb - after allocating and freeing 1,000,000 ints  
  2780kb - after allocating and freeing 2,000,000 ints  
 65216kb - after allocating and freeing 4,000,000 ints  

我在Fedora Core 6上运行并使用GCC 4.1.1。

2 个答案:

答案 0 :(得分:11)

C库使用的内存分配器根据块的大小以各种方式分配内容。当释放内存时,页面并不总是返回到操作系统,特别是如果你做了很多小的分配。

内存只能逐页返回到操作系统,而不能用于小的分配。

如果您真的需要知道,请检查C库源代码并检测它等。

在C ++中,您可以覆盖容器的分配器以进行自己的内存管理 - 然后您可以随意执行任何操作(例如mmap / dev / zero或其他)

答案 1 :(得分:5)

这取决于,通常如果你使用Linux盒子,底层的malloc将开始在堆中分配东西并且它会增长,但是如果你释放一些大的内部块,它将无法释放任何东西,直到顶部堆的一部分被释放,因为它可以做的onyl事情是增加或减少堆。

所以,如果你分配一个巨大的块,后来一个较小的块,然后释放你的bug块,可能会发生它们按顺序放置,直到你释放较小的块,你的进程将无法减少堆大小

在您当前的示例中,可能会发生第一次释放您没有等待下一次分配,之后无法释放它们,因为您已经在其上分配了一些内容。或者它可能不会开始释放直到给定的内存大小。