【发布时间】:2017-07-11 06:57:43
【问题描述】:
用 C++ 编写这个简单的代码:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Empty{};
int main() {
array<unique_ptr<Empty>, 1024> empties;
for(size_t i =0; i < 1024; i++){
empties[i] = make_unique<Empty>();
}
for(auto& element : empties){
cout << "ptr: " << element.get() << endl;
}
return 0;
}
在 ideone.com 或 Windows 中运行时,我们得到以下结果:
ptr: 0x2b601f0c9ca0
ptr: 0x2b601f0c9cc0
ptr: 0x2b601f0c9ce0
ptr: 0x2b601f0c9d00
ptr: 0x2b601f0c9d20
ptr: 0x2b601f0c9d40
ptr: 0x2b601f0c9d60 ...
对我来说这很奇怪。操作系统或标准库中什么样的分配算法可能会导致地址没有分配,其结尾的数字不是0?
我做这个实验的原因是,鉴于操作系统使用伙伴算法,管理页面和分配请求将导致操作系统分配一块连续的内存,然后分配几个下一个分配(直到用完分配的内存)应该分配在附近。如果是这样的话,那么在某些情况下,列表的缓存问题可能不会那么重要,但我得到了我没想到的结果。
分配节点中从右数第二个数字也是完全随机的。什么可能导致这种行为?
【问题讨论】:
-
我不知道您使用的是什么操作系统,但至少 Linux 将所有堆分配对齐为 16 字节。一些像 llvm 团队这样狡猾的人实际上使用这个事实来存储那些总是零位的东西。
-
操作系统本身与此无关。操作系统分配页面,程序的分配器(可能来自您动态链接到的标准库,可能随操作系统提供,但不是操作系统本身)将页面细分为分配的块。它可能需要一些空间用于跟踪信息,出于效率/碎片相关原因对齐分配等。空分配成本 32 字节并非不合理/闻所未闻。
-
即使结构是空的,它仍然需要有一个可寻址的大小。添加到该大小的将是系统分配器对齐和填充。
-
连续指针值之差为 32(字节)。这不是“完全随机的”。看起来很正常,符合我的预期。
-
@SanderDeDycker 对我来说预计是 8 个字节,因为它是可寻址单元的最小化
标签: c++ c++11 memory memory-management dynamic-memory-allocation