Выравнивание структуры памяти - время компиляции и динамически выделяемая память
Я просто просматривал руководство по glibc для описания функции posix_memalign, когда столкнулся с этим утверждением:
Адрес блока, возвращаемого функцией malloc или realloc в системе GNU, всегда кратен восьми (или шестнадцати в 64-битных системах). Если вам нужен блок, адрес которого кратен большей степени, чем два, используйте memalign, posix_memalign или valloc.
Если я рассмотрю простую структуру, содержащую только элемент данных int:
struct Mystruct
{
int member;
};
Тогда я вижу, что Mystruct должно быть выровнено на 4 байта. Но согласно руководству libc по 64-битной архитектуре, динамическое выделение памяти для такой структуры вернет память, выделенную по адресу с 16-байтовым выравниванием.
Поправь меня, если я ошибаюсь. Мне кажется, что компилятор использует естественное выравнивание структуры только для глобальных / статических / автоматических переменных (data, bss, stack). Но, с другой стороны, чтобы выделить ту же структуру в памяти кучи, вызов malloc использует предопределенное выравнивание (8 на 32-битных архитектурах и 16 на 64-битных архитектурах)?
1 ответ
Стоит помнить, что в malloc () нет ничего волшебного - это просто функция. Точно так же, куча - это просто куча памяти, которую компилятор обещает не трогать. Статическое распределение объектов (в стеке или в data/bss) - это то, что делает компилятор, поэтому он может выравнивать их в соответствии с указанным выравниванием. malloc () (и связанные функции) - это функции, которые управляют кучей, но они вызываются во время выполнения. Компилятор ничего не знает о malloc (), за исключением того, что это функция, а malloc () не знает ничего о памяти, которую вы просите выделить, кроме того, сколько вы запрашиваете. Поскольку 16-разрядное выравнивание обычно подходит для большинства распространенных применений, malloc() обеспечивает безопасное выравнивание.
PS: забавное (и открывающее глаза) упражнение - написать собственную реализацию malloc ().