Меня беспокоят операции выравнивания и Interlocked
. Очередной раз. В документации для этих функций указано, что переменная, которую мы хотим обновить, должна быть выровнена по 32-битной границе, и что мы можем добиться этого с помощью _aligned_malloc
. Отлично.
Итак, у меня есть небольшая тестовая программа:
struct S
{
char c;
long l;
}an_S;
printf("%p, %p", (void*)(&(an_S.c)), (void*)(&(an_S.l)));
В режиме выпуска вывод из этого всегда дает мне адрес long, который находится на 4 байта после адреса char, поэтому он начинается на 32-битной границе.
1) Это чисто случайно, или я могу полагаться на это, следовательно, нет необходимости в _aligned_malloc
?
2) Если мне нужно использовать aligned_malloc
, может кто-нибудь уточнить, как это сделать? Я прочитал документацию на https://msdn.microsoft.com/en-us/library/8z34s9c6.aspx, но, похоже, это не показывает, как присвоить значение памяти, которая `` выделена '' ...
3) (Предполагая, что мне действительно нужен aligned_malloc
) Если мне нужен массив структур с длинной переменной, подобной приведенной выше, с которой нужно работать с помощью операции Interlocked, мне нужно добавить какой-то конструктор, чтобы настроить это или есть ли более простой способ сделать это?
4) Я выполнил поиск в Google по запросу _aligned_malloc + interlockedCompareExchange, и он выкупил только 70 результатов. Это говорит мне, что либо большая часть кода, который использует InterlockedCompareExchange
(62 800 результатов), либо неверна, либо _aligned_malloc
не нужен. Может кто-нибудь уточнить?
На это можно положиться, если использовать выровненные конструкции. Это по умолчанию. Также выравниваются локальные переменные. malloc тоже в порядке. Если вы не хотите необычного выравнивания, например, 16 байт.
Внутри struct S
, long l
будет на расстоянии X байтов от начала char c
, где X - выравнивание struct S
. Но это не гарантирует, что экземпляры struct S
, такие как an_s
, выделяются по выровненным адресам памяти, поэтому l
не всегда может находиться на выровненной 32-битной границе. Это зависит от выравнивания, используемого при объявлении struct S
, и выравнивания кода, который выделяет struct S
.
@ Реми Лебо, я в замешательстве. Дэвид Хеффернан говорит ниже, что структуры по умолчанию выровнены. Я не говорю, что вы ошибаетесь, я говорю, что не знаю, что правильно: \ Кроме того, en.wikipedia.org/wiki/Data_structure_alignment сообщает мне Тип каждого члена структуры обычно имеет выравнивание по умолчанию. - значит, если первый член выровнен, все остальные участники после этого будут выровнены?
@Wad, предназначенный для выравнивания По умолчанию. Посмотрите на #pragma pack
, alignas
и другие подобные директивы компилятора, которые влияют на выравнивание. Подумайте, что происходит, когда структура имеет выравнивание <4 или содержится в другой структуре с выравниванием <4. long l
в struct S
не будет правильно выровнен для блокированного / атомарного доступа.
Ладно, ладно. Итак, пока я придерживаюсь выравнивания по умолчанию и не использую какие-либо из этих директив, я в порядке - правильно?
по раскладу у вас ок. для кода - нет
Если ваши структуры выровнены, что является значением по умолчанию, то каждый элемент будет выровнен в соответствии с типом элемента.
Что касается malloc
, документация для MSVC объясняет, что для 32 целей память выровнена по 8 байт, для 64-битных целей она выровнена по 16 байт. Итак, вы можете использовать malloc
.
Хорошо, спасибо. Я обсуждал это с коллегой, который предполагает, что причина, по которой MSDN подчеркивает, что переменные должны быть выровнены на 32 бита, заключается в том, что кто-то делает что-то (глупое?), Например, индексирует массив символов и приводит результат как длинный, а затем использует это в функция блокировки; вы бы согласились?
Да, это одна из возможностей. Другой - использование упакованных структур данных.
_aligned_malloc
здесь не нужен. иlong l
будет выровнен по 4 байтам, если вы не используете#pragma(pack, N)
, гдеN
меньше 4 (2 или 1). и вообще, исходя из вашего первоначального вопроса, вам нужно абсолютно другое - защита от кратковременного отказа