Я хочу сделать структурную форму / макет более «определенным / исправленным» и менее «на усмотрение компилятора». Структура структуры будет совместно использоваться при передаче между архитектурами x86_64 и ARMv7-A. Да, это вообще не переносимо, но для этого более ограниченного случая порядок байтов тот же (и может быть преобразован, если решено использовать на другой платформе).
Существуют ли требования выравнивания для разных типов / размеров данных на ARMv7-A? (т.е. их неправильное использование — неопределенное поведение)
Или это может упаковать их для любого выравнивания? (то есть это все определенное поведение)
Некоторые выравнивания дают лучшую производительность, чем другие?
Я читал о требованиях к упаковке / выравниванию для ARM, но, к сожалению, я заметил, что он немного устарел относительно моей архитектуры.
http://www.aleph1.co.uk/chapter-10-arm-structured-alignment-faq
Я использовал заголовки, как это, на обеих архитектурах:
#pragma pack(4)
struct foo
{
uint8_t bar1; // 1 byte, the 3 padding bytes
std::array<double,1> bar2; // 8 bytes
};
#pragma pack()
Я использую кросс-компилятор GCC для ARM: gcc -Wall -Wextra -Wcast-align -march=armv7-a -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a9
Когда я звоню foo abc; abc.bar2.data();
и скомпилировать с -fsanitize=undefined
выдает ошибку во время выполнения:
-fsanitize=address
runtime error: member call on misaligned address 0xbeeb0c44 for type 'struct array', which requires 8 byte alignment
0xbeeb0c44: note: pointer points here
01 00 00 00 03 00 00 00 03 00 00 00 01 00 00 00 f4 0d eb be fc 0d eb be c0 a5 00 00 00 00 db 4b
^
/sysroot.../usr/include/c++/5.2.0/array:230:32: runtime error: reference binding to misaligned address 0xbeeb0c44 for type 'const double', which requires 8 byte alignment
0xbeeb0c44: note: pointer points here
01 00 00 00 03 00 00 00 03 00 00 00 01 00 00 00 f4 0d eb be fc 0d eb be c0 a5 00 00 00 00 db 4b
^
Мне нравится доверять дезинфицирующему средству, и это заставляет меня думать, что это плохо. Однако, если я выключу дезинфицирующие средства и включу оптимизацию до -O3
вела себя нормально. Однако мне может быть (не) повезло, и этот случай неопределенного поведения, кажется, работает нормально. Я помню, раньше у меня было предупреждение -Wcast-align, когда я делал pack (1) вместо pack (4), но я не могу вспомнить, как я получал к нему доступ, чтобы вызвать это срабатывание. Я предполагаю, что это также указывает на то, что это было, вероятно, неопределенное поведение. Правда ли, что адрес sanitiser и -Wcast-align указывали на неопределенное поведение для этой архитектуры, даже если она работала?
Было бы рекомендовано увеличить пакет (8), чтобы исправить неопределенное поведение? К сожалению, это увеличивает использование памяти.
В заключение, является pragma pack(n)
или же __attribute__((packed))
для каждого объекта структуры предпочтительный способ сделать это? (__attribute__((packed))
является расширением GCC и, к сожалению, не может указать размер пакета.)
Для невыровненного доступа всегда будет снижение производительности, потому что для одного доступа вам может потребоваться прикоснуться к двум строкам кэша.
Я предполагаю, что точная реакция на не выровненный доступ (замедление или сбой) не определяется описанием архитектуры, но может быть оставлена на усмотрение реализации.
Когда вы просто следуете старой привычке упорядочения полей в структуре по убыванию размера, тогда все сегодняшние компиляторы C (++) будут создавать одинаковую схему памяти. Я бы предложил этот путь, чтобы спасти вас от горя.
Других решений пока нет …