c++ - 巨大的 std::vector<std::vector> 不会在销毁时释放所有内存

标签 c++ memory vector

当使用一个非常大的 vector vector 时,我们发现部分内存没有被释放。

#include <iostream>
#include <vector>
#include <unistd.h>

void foo()
{
    std::vector<std::vector<unsigned int> > voxelToPixel;
    unsigned int numElem = 1<<27;
    voxelToPixel.resize( numElem );

    for (unsigned int idx=0; idx < numElem; idx++)
        voxelToPixel.at(idx).push_back(idx);

}

int main()
{
    foo();
    std::cout << "End" << std::endl;
    sleep(30);
    return 0;
}

这会留下大约 4GB 的内存,直到进程结束。

如果我们将 for 行更改为

for (unsigned int idx=0; idx < numElem; idx++)
    voxelToPixel.at(0).push_back(idx);

内存被释放。

在 linux 机器上使用 gcc-4.8。我们使用 htop 来跟踪具有 100 GB RAM 的计算机上的内存使用情况。您将需要大约 8 GB 的 RAM 来运行代码。你能重现这个问题吗?关于为什么会发生这种情况的任何想法?

编辑: 我们已经看到这在 Mac 中不会发生(使用 gccclang)。此外,在 linux 中,如果我们调用 foo 两次(但第三次再次发生),内存就会被释放。

最佳答案

小型分配(我认为默认情况下最大为 128kb)由进程内堆管理,并且在释放时不会返回给操作系统;它们被返回到堆中以在进程中重用。较大的分配直接来自操作系统(通过调用 mmap),并在解除分配时返回给操作系统。

在您的第一个示例中,每个 vector 只需要为单个 int 分配足够的空间。你有一亿个小分配,没有一个会返回给操作系统。

在第二个示例中,随着 vector 的增长,它将进行许多不同大小的分配。有些小于 mmap 阈值,这些将保留在进程内存中;但是,由于您只对一个 vector 执行此操作,因此数量不会很大。如果您在填充之前使用 resizereserve 为每个 vector 分配所有内存,那么您应该会发现所有内存都返回给了操作系统。

关于c++ - 巨大的 std::vector<std::vector> 不会在销毁时释放所有内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26020580/

相关文章:

c++ - Solaris 10 x86 C++ 上的 GetThreadTimes

c - 了解多线程共享资源 : shmid, shmat、shmdt

c++ - 将 char 数组结构 vector 转换为 POD vector ?

java - 两个不同长度 vector 的欧氏距离

c - 如何在 C 中使用一个引用创建多个内存块

c++ - 我无法动态声明 vector 数组

c++ - 如何通过引用从 MQL4 向 C++ DLL 传递参数

c++ - 使用 C 预处理器指令建立 GCC/G++ 链接

c++ - 在 C++ 中解析逗号分隔的整数/整数范围

c - 函数参数是否占用本地内存空间?