内存分配的时间间隔

时间:2015-10-10 01:49:54

标签: c struct malloc

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个字节?

1 个答案:

答案 0 :(得分:2)

大多数内存分配器不是无开销的 - 在每个分配的块之前和/或之后,分配器内部使用了一些额外的内存。

在系统的内存分配器中,每个分配块的开销似乎达到8个字节。这对于32位系统来说非常典型;它可能存储分配块的大小(4个字节)和指向前一个块的指针(4个字节),或类似的东西。

要记住的另一个因素是许多分配器具有最小分配量 - 即,每个分配块的“实际”大小向上舍入到标准大小的最接近倍数。这是因为某些CPU特性(特别是向量操作)通常要求存储器与某个边界对齐,并且因为非常小的块很难跟踪。在你的系统上,量子可能是八个字节,所以这在你的例子中没有发挥作用。 (您可以通过将结构中的一个成员从int更改为char来证明此效果。)