我想让结构表单/布局更“定义/固定”,而不是“由编译器自行决定”。在 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()
我正在为 ARM 使用 GCC 交叉编译器: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
,它的行为还可以。但是我可能只是(不)幸运,这种未定义行为的情况似乎工作正常。我记得早些时候我在执行 pack(1) 而不是 pack(4) 时触发了 -Wcast-align 警告,但我不记得我是如何访问它来触发它的。我认为这也表明它可能是未定义的行为。地址清理程序和 -Wcast-align 是否确实表明了此架构的未定义行为,即使它似乎有效?
是否建议增加 pack(8) 来修复未定义的行为?不幸的是,它确实增加了内存使用量。
最后,或者对于每个结构实体来说,这样做的首选方式是什么?pragma pack(n)
__attribute__((packed))
(__attribute__((packed))
是 GCC 扩展,遗憾的是无法指定包大小。)