打包一个结构是否会错位相邻的内存?
Will packing a struct ever misalign adjacent memory?
考虑以下结构
struct a{
uint16_t foo1
uint16_t foo2
uint32_t foo3
uint64_t foo4
uint16_t foo5
uint16_t foo6
}__attribute__(packed);
它有 20 个字节长。这很好,因为结构中的所有内容都与单词边界对齐。
但是,如果好心的开发人员执行以下操作,会发生什么情况:
static struct a foo;
static uint64_t b;
从理论上讲,这会使 b 在字边界上错位。
有趣的是,gcc 似乎将 foo
对齐到 16 个字节,但是(如果我对汇编的了解是正确的),它允许 b 未对齐:
.local foo.2476
.comm foo.2476,20,16
.local b.2477
.comm b.2477,8,8
我是不是遗漏了什么,或者这是结构打包的危险示例?
However, what happens if a well-meaning developer does the following:
static struct a foo;
static uint64_t b;
This would, theoretically, misalign b across a word boundary.
不,在那种情况下 b
没有特别的原因会错位,如果你
static char foo;
static uint64_t b;
。假设 uint64_t
的对齐要求大于 1,那么质量较差的编译器 可能 在这种情况下不对齐 b
,但实际上,您永远不可能看到这样的结果。编译器自行决定为变量布置存储空间,通常位于对齐良好的地址。
Interestingly, gcc seems to align foo to 16 bytes, however (if my knowledge of assembly is correct), it allows b to be misaligned:
[...]
Am I missing something here, or is this an example of the dangers of struct packing?
您几乎肯定遗漏了什么。我敢打赌你的机器 uint64_t
有 4 字节而不是 8 字节的对齐要求。
考虑以下结构
struct a{
uint16_t foo1
uint16_t foo2
uint32_t foo3
uint64_t foo4
uint16_t foo5
uint16_t foo6
}__attribute__(packed);
它有 20 个字节长。这很好,因为结构中的所有内容都与单词边界对齐。
但是,如果好心的开发人员执行以下操作,会发生什么情况:
static struct a foo;
static uint64_t b;
从理论上讲,这会使 b 在字边界上错位。
有趣的是,gcc 似乎将 foo
对齐到 16 个字节,但是(如果我对汇编的了解是正确的),它允许 b 未对齐:
.local foo.2476
.comm foo.2476,20,16
.local b.2477
.comm b.2477,8,8
我是不是遗漏了什么,或者这是结构打包的危险示例?
However, what happens if a well-meaning developer does the following:
static struct a foo; static uint64_t b;
This would, theoretically, misalign b across a word boundary.
不,在那种情况下 b
没有特别的原因会错位,如果你
static char foo;
static uint64_t b;
。假设 uint64_t
的对齐要求大于 1,那么质量较差的编译器 可能 在这种情况下不对齐 b
,但实际上,您永远不可能看到这样的结果。编译器自行决定为变量布置存储空间,通常位于对齐良好的地址。
Interestingly, gcc seems to align foo to 16 bytes, however (if my knowledge of assembly is correct), it allows b to be misaligned: [...]
Am I missing something here, or is this an example of the dangers of struct packing?
您几乎肯定遗漏了什么。我敢打赌你的机器 uint64_t
有 4 字节而不是 8 字节的对齐要求。