qui*_*uss 22 c++ memory 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;
}
Run Code Online (Sandbox Code Playgroud)
这将留下大约4GB的内存,直到进程结束.
如果我们将for行更改为
for (unsigned int idx=0; idx < numElem; idx++)
voxelToPixel.at(0).push_back(idx);
Run Code Online (Sandbox Code Playgroud)
记忆被释放了.
使用gcc-4.8Linux机器上.我们习惯于htop在具有100 GB RAM的计算机上跟踪内存使用情况.您将需要大约8 GB的RAM来运行代码.你能重现这个问题吗?关于为什么会发生这种情况的任何想法?
编辑:我们已经看到,这不会发生在Mac(任何一个gcc或clang).此外,在linux中,如果我们调用foo两次(但第三次再次发生),则释放内存.
Mik*_*our 27
小分配(我认为默认情况下高达128kb)由进程内堆管理,并且在取消分配时不会返回给操作系统; 它们将返回堆中以便在进程中重用.较大的分配直接来自OS(通过调用mmap),并在解除分配时返回到OS.
在第一个示例中,每个向量只需要为单个向量分配足够的空间int.您有一亿个小分配,其中任何一个都不会返回给操作系统.
在第二个例子中,随着向量的增长,它将进行多种不同大小的分配.有些小于mmap阈值,这些将保留在进程内存中; 但是,因为你只对一个向量执行此操作,所以这不会是一个巨大的数量.如果您在填充之前使用resize或reserve分配每个向量的所有内存,那么您应该发现所有内存都返回给操作系统.