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

Posted

技术标签:

【中文标题】在 C++ 中,即使调用了 delete,进程何时会保留分配的内存?【英文标题】:In C++, when does a process retain allocated memory even though delete is called? 【发布时间】:2009-08-11 10:53:50 【问题描述】:

我想了解在以下情况下 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 - 开始 18356kb - 在分配和释放 1,000,000 个整数之后 2780kb - 在分配和释放 2,000,000 个整数之后 65216kb - 分配和释放 4,000,000 个整数后

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

【问题讨论】:

为什么会出现这个问题?它会导致内存不足吗? 问题是由于内存使用量高的情况下交换导致机器速度变慢;如果内存实际上已被应用程序释放,我想避免的事情。 【参考方案1】:

C 库使用的内存分配器根据块的大小以多种方式分配内容。当内存被释放时,页面并不总是返回给操作系统,尤其是当您进行许多小分配时。

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

如果您确实需要了解,请检查 C 库源代码并对其进行检测等。

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

【讨论】:

除非您自己进行内存管理,否则很少会返回给操作系统。标准内存管理(我看过的实现)保留了操作系统提供的所有内容。【参考方案2】:

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

因此,如果您分配一个大块,然后分配一个较小的块,然后释放您的错误块,则它们可能会按顺序放置,直到您释放较小的块,您的进程将无法减少堆大小。

在您当前的示例中,您所做的第一次释放可能不会等待下一次分配,后来它们无法被释放,因为您在其上分配了一些东西。或者它可能在给定的内存大小之前不会开始释放。

【讨论】:

以上是关于在 C++ 中,即使调用了 delete,进程何时会保留分配的内存?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 析构函数何时被调用?

C++ 析构函数何时被调用?

如何在运行时确定您的 C++ 应用程序何时附加了 Visual Studio 调试器?

C++ 动态内存 new/delete用法

C++中delete与 delete []区别

如何使 libcurl C++ 调用超时和/或知道调用中何时发生超时