当使用一个非常大的 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 中不会发生(使用 gcc
或 clang
)。此外,在 linux 中,如果我们调用 foo
两次(但第三次再次发生),内存就会被释放。
最佳答案
小型分配(我认为默认情况下最大为 128kb)由进程内堆管理,并且在释放时不会返回给操作系统;它们被返回到堆中以在进程中重用。较大的分配直接来自操作系统(通过调用 mmap
),并在解除分配时返回给操作系统。
在您的第一个示例中,每个 vector 只需要为单个 int
分配足够的空间。你有一亿个小分配,没有一个会返回给操作系统。
在第二个示例中,随着 vector 的增长,它将进行许多不同大小的分配。有些小于 mmap
阈值,这些将保留在进程内存中;但是,由于您只对一个 vector 执行此操作,因此数量不会很大。如果您在填充之前使用 resize
或 reserve
为每个 vector 分配所有内存,那么您应该会发现所有内存都返回给了操作系统。
关于c++ - 巨大的 std::vector<std::vector> 不会在销毁时释放所有内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26020580/