Интервал выделения памяти
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 ответ
Большинство распределителей памяти не являются свободными - есть некоторое количество дополнительной памяти, используемой внутренне распределителем, предшествующим и / или следующим за каждым выделенным блоком.
В распределителе памяти вашей системы эти накладные расходы достигают восьми байт на выделенный блок. Это довольно типично для 32-битной системы; вероятно, он хранит размер выделенного блока (4 байта) и указатель на предыдущий блок (4 байта) или что-то подобное.
Еще один фактор, который нужно иметь в виду, состоит в том, что многие распределители имеют минимальный квант выделения, то есть "реальный" размер каждого выделенного блока округляется до ближайшего кратного стандартного размера. Это связано с тем, что определенные функции ЦП (особенно векторные операции) часто требуют выравнивания памяти по определенной границе, а также потому, что очень маленькие блоки неудобно отслеживать. В вашей системе квант, вероятно, составляет восемь байтов, поэтому в вашем примере это не входит в игру. (Вероятно, вы можете продемонстрировать этот эффект, изменив один из членов вашей структуры с int
к char
.)