Ссылка на этот вопрос и ответ Выравнивание памяти: как использовать alignof / alignas? «Выравнивание — это ограничение, в котором в памяти можно хранить первый байт значения». Существует ли в C ++ портативный способ определения максимальной детализации выравнивания, которая требуется для инструкций, которые не вызывают ошибки (например, в ARM)? Является alignof(intmax_t)
достаточно, так как это самый большой целочисленный примитивный тип?
Далее, как что-то в malloc выравнивает данные по границам структуры? Например, если у меня есть такая структура
alignas(16) struct SomethingElse { ... };
SomethingElse
Структура должна быть выровнена по границе, кратной 16 байтам. Теперь, если я запрашиваю память для структуры из malloc, как это
SomethingElse* ptr = malloc(sizeof(SomethingElse));
Что происходит, когда malloc возвращает указатель, который указывает на такой адрес, как 40
? Это неверно, так как указатель на SomethingElse
объекты должны быть кратны 16?
Возможно, вы ищете std::max_align_t
Как определить максимальное требование к выравниванию данных в C ++
Есть std::max_align_t
который
тип POD, требования к выравниванию которого, по крайней мере, такие же строгие (такие же большие), как и для каждого скалярного типа
Векторные инструкции могут использовать операнды массива, которые требуют более высокого выравнивания, чем любой скаляр. Я не знаю, есть ли портативный способ узнать верхнюю границу для этого.
Чтобы найти требование выравнивания для определенного типа, вы можете использовать alignof
,
Далее, как что-то в malloc выравнивает данные по границам структуры?
malloc
выравнивается по некоторой границе, достаточной для любого скаляра. На практике точно так же, как std::max_align_t
,
Он не будет правильно выровнен для типов с «совмещением». Под оверлайном я подразумеваю тип с более высоким требованием выравнивания, чем std::max_align_t
,
Что происходит, когда malloc возвращает указатель, который указывает на адрес, например, 40?
Разыменование такое SomethingElse*
будет иметь неопределенное поведение.
Это неверно, так как указатель на объекты SomethingElse должен быть кратным 16?
Да.
как еще можно было бы исправить это? Нет никакого способа сказать malloc выравнивание, которое вы хотите, верно?
Чтобы выделить память для типов с перестроением, вам нужно std::aligned_alloc
который должен быть представлен в C ++ 17.
До тех пор, вы можете использовать платформо-зависимые функции, такие как posix_memalign
или вы можете выделить более std::malloc
(выделите выравнивание — 1 ценность дополнительных байтов), затем используйте std::align
найти правильную границу. Но тогда вы должны отслеживать как начало буфера, так и начало блока памяти отдельно.