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

Dav*_*ick 4 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;
}
Run Code Online (Sandbox Code Playgroud)

我通过运行"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.

Mar*_*rkR 11

C库使用的内存分配器根据块的大小以各种方式分配内容.释放内存时,页面并不总是返回到操作系统,特别是如果您执行许多小分配.

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

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

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

  • 除非您自己进行内存管理,否则很少会返回到操作系统.标准内存管理(我已经看过的实现)保留了操作系统给出的所有内容. (3认同)

Ark*_*nez 5

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

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

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