Я хочу сделать форму/макет структуры более «определенной/фиксированной» и менее «на усмотрение компилятора». Макет структуры будет общим при обмене данными между архитектурами x86_64 и ARMv7-A. Да, в целом он не переносим, но для этого более ограниченного случая порядок следования байтов одинаков (и может быть преобразован, если будет решено использовать его на другой платформе).
Существуют ли требования к выравниванию для разных типов/размеров данных в ARMv7-A? (т. е. их неправильное использование является поведением undefined)
Или он может упаковать их в любое выравнивание? (т. е. это все определенное поведение)
Для некоторых выравниваний производительность выше, чем у других?
Я читал о требованиях к упаковке/выравниванию для 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), но я не могу вспомнить, как я обращался к нему, чтобы это сработало. Я предполагаю, что это также указывает на то, что это, вероятно, было неопределенное поведение. Правда ли, что средство очистки адресов и -Wcast-align указывали на неопределенное поведение для этой архитектуры, хотя казалось, что оно работает?
Не рекомендуется ли увеличить до pack(8), чтобы исправить неопределенное поведение? К сожалению, это увеличивает использование памяти.
Наконец, является ли предпочтительным способом сделать это pragma pack(n)
или __attribute__((packed))
для каждого объекта структуры? (__attribute__((packed))
является расширением GCC, и, к сожалению, не может указать размер пакета.)