当使用非常大的矢量矢量时,我们发现部分内存未被释放。
#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中不会发生这种情况(gcc
或clang
)。此外,在linux中,如果我们调用foo
两次(但第三次再次发生),则释放内存。
答案 0 :(得分:27)
小分配(我认为默认情况下高达128kb)由进程内堆管理,并且在取消分配时不会返回给操作系统;它们将返回堆中以便在进程中重用。较大的分配直接来自操作系统(通过调用mmap
),并在解除分配时返回到操作系统。
在第一个示例中,每个向量只需要为单个int
分配足够的空间。您有一亿个小分配,其中任何一个都不会返回给操作系统。
在第二个例子中,随着向量的增长,它将进行多种不同大小的分配。有些小于mmap
阈值,这些将保留在进程内存中;但是,因为你只对一个向量执行此操作,所以这不会是一个巨大的数量。如果您在填充之前使用resize
或reserve
为每个向量分配所有内存,那么您应该会发现所有内存都返回给操作系统。