我正在通过将文件映射到内存并通过C结构定义访问它来解析文件格式。该文件格式使用紧凑的结构,因此我无法保证字段将对齐到字边界。
解析工作正常,但不幸的是,在某些情况下优化器可能会造成破坏。特别是在编译armv7时,有些加载指令需要字对齐,而其他加载指令则不需要。考虑以下代码片段:
在
在
解析工作正常,但不幸的是,在某些情况下优化器可能会造成破坏。特别是在编译armv7时,有些加载指令需要字对齐,而其他加载指令则不需要。考虑以下代码片段:
#define PACKED __attribute__((packed))
typedef struct PACKED _Box_mvhd {
union {
struct {
int32_t creation_time;
int32_t modification_time;
int32_t time_scale;
int32_t duration;
...
} v0;
} data;
} Box_mvhd;
Container mvhd = find_single_box(&moov, 'mvhd');
if (mvhd.boxStart) {
Box_mvhd *mvhdBox = mvhd.mvhd;
if (0 == mvhdBox.box.version) {
uint32_t ts = ntohl(mvhdBox->data.v0.time_scale);
uint32_t dur = ntohl(mvhdBox->data.v0.duration);
...
}
}
在
-O0
(调试)模式下,最内层的块会被编译为以下的汇编代码,其可以正常工作:ldr r1, [r0, #24]
ldr r2, [r0, #20]
在
-O2
编译优化级别下,编译器会意识到这些字段是相邻的,并生成以下汇编代码:ldrdeq r2, r3, [r0, #20]
很不幸,由于规范和实践,LDRD
总是会生成对齐错误。因此,我需要一种有效地通知编译器这个问题的方式。理想情况下,这可以通过在结构上使用属性来完成。也有可能这是编译器或ARM后端的一个bug,但我愿意相信这不是。
我正在使用Xcode 4.2 (clang 3.0)编译,目标是面向iPhone的armv7。
mvhdBox
(r0
)本身是否未对齐?如果是这样,你应该将数据memcpy
到适当对齐的缓冲区中,从那里访问它,并删除填充属性。 - R.. GitHub STOP HELPING ICEalignof(Box_mvhd)
返回什么?(如果clang不原生支持alignof()
,您可以使用类似于#define alignof(t) offsetof(struct { char c; t x; }, x)
的方法) - Michael BurrBox_mvhd *
,然后访问字段。 - Stephen Canonunsigned char[]
文件缓冲区中使用memcpy
复制到一个真正的(因此正确对齐)Box_mvhd
类型的对象中。 - R.. GitHub STOP HELPING ICE