2

我想让结构表单/布局更“定义/固定”,而不是“由编译器自行决定”。在 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 扩展,遗憾的是无法指定包大小。)

4

1 回答 1

0

未对齐的访问总会有性能损失,因为对于单次访问,​​您可能必须触及两个缓存行。

我猜想架构描述没有定义对未对齐访问(减速或故障)的确切反应,但可能留给实现。

如果您只是遵循按大小递减对结构中的字段进行排序的旧习惯,那么今天所有的 C(++) 编译器都会产生相同的内存布局。我建议这条路线让你免于悲伤。

于 2016-09-22T09:07:47.657 回答