struct Thing
{
int member1;
int member2;
};
struct Thing* heap()
{
struct Thing* heap_thing = (struct Thing*)malloc(sizeof(struct Thing));
heap_thing->member1 = 1;
heap_thing->member2 = 2;
printf("%p, %p, %p\n", heap_thing, &(heap_thing->member1), &(heap_thing->member2));
return heap_thing;
}
int main(int argc, char* argv[])
{
struct Thing* ptr = 0;
for (int i = 0; i < 5; ++i)
{
ptr = heap();
free(ptr);
}
return 0;
}
我希望打印的内存地址类似于:
(因为struct Thing
是8个字节)
0x000008, 0x000008, 0x00000c
0x000010, 0x000010, 0x000014
0x000018, 0x000018, 0x00001c ......
但我的屏幕上显示的是:
0x000008, 0x000008, 0x00000c
0x000018, 0x000018, 0x00001c
0x000028, 0x000028, 0x00002c ......
为什么struct Thing
成员的内存地址没有按照我的预期分配? ptr
之间的内存地址有16个字节的间隔但不是8个字节?
答案 0 :(得分:2)
大多数内存分配器不是无开销的 - 在每个分配的块之前和/或之后,分配器内部使用了一些额外的内存。
在系统的内存分配器中,每个分配块的开销似乎达到8个字节。这对于32位系统来说非常典型;它可能存储分配块的大小(4个字节)和指向前一个块的指针(4个字节),或类似的东西。
要记住的另一个因素是许多分配器具有最小分配量 - 即,每个分配块的“实际”大小向上舍入到标准大小的最接近倍数。这是因为某些CPU特性(特别是向量操作)通常要求存储器与某个边界对齐,并且因为非常小的块很难跟踪。在你的系统上,量子可能是八个字节,所以这在你的例子中没有发挥作用。 (您可以通过将结构中的一个成员从int
更改为char
来证明此效果。)