const size_t size = 10000000;
using T = unsigned short[];
vector<unique_ptr<T>> v;
v.resize(size);
for (size_t n = 0; n != size ; ++n) {
v[n] = make_unique<T>(3);
for (int i = 0; i!= 3; ++i)
v[n][i] = rand();
}
我想测量它使用了多少内存。为什么实际尺寸是 valgrind 显示器的 3 倍?
我在 VSL、ubuntu 上运行它。
最佳答案
您忘记了内存分配本身的开销。只需 new
/delete
本身:有东西必须跟踪它。某处。
您很容易,但 C++ 库会为您完成所有艰苦的工作。
你很容易:你只需new
一些任意数量的字节,和delete
稍后,你就完成了。但对于 C++ 库来说,这并不容易。它必须知道每个有多大new
ed 对象或对象是。所以当他们是 delete
d C++ 库知道刚刚删除了多少内存。当内存中的相邻对象得到delete
d,分配器也需要意识到这一点,并将两个相邻的 delete
结合起来。 d 个对象合并到一个更大的内存块中,以便它可以潜在地用于 new
一个更大的物体,在稍后的某个时间点。
这种复杂性不是免费的。需要对其进行跟踪和汇总。
所有这些爵士乐都至少需要一个指针值和一个字节计数值。按分配。一个健壮的内部内存分配器可能希望在某个地方存储一个额外的指针,但让我们从一个指针和一个字节数开始,作为内存分配器的一个极简实现。
您正在分配 sizeof(unsigned short)*3
一次字节,或者按我的计数为 6 个字节。在 64 位平台上,指针需要 8 个字节长。假设您有一个智能内存分配器,它维护一个单独的 bool 分配,其大小不超过 64kb,因此内存字节数只需 2 个字节。所以这是每次分配十字节的开销。
该开销需要存储、跟踪并堆积到 每分配。因此,考虑到每分配 6 个字节至少有 10 个字节的额外开销,观察到使用 2-3 的预期内存量似乎几乎在球场上。如果字节计数在内部被跟踪为 4 个字节,或者如果内存池是双向链表,则肯定在球场上,需要 另一个 8 个字节(如果幸运的话,可能是 4 个字节)混在一起。
关于c++ - 使用 valgrind 进行堆分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65790333/