【问题标题】:Why does my structure element carry padding bytes?为什么我的结构元素带有填充字节?
【发布时间】:2023-03-18 22:40:01
【问题描述】:

我对结构元素的内存对齐有一个令人困惑的行为。考虑这两种结构:

typedef struct s_inner {
    unsigned long ul1;
    double        dbl1;
    fourth_struct s4;
    unsigned long ul2;
    int           i1;
} t_inner;

typedef struct s_outer {
    other_struct    member1; /* 4-byte aligned, 40 bytes in terms of sizeof() */
    unsigned long   member2;
    t_inner         member3; /* see above */
} t_outer;

当我检查 t_outer 的内存布局时,我可以看到 member1 的元素是 4 字节对齐的,正如我所期望的那样。 member3 的内存布局也符合预期:ul1 附加了 4 个填充字节,因此 dbl1 在 8 字节边界上对齐(在 Win32 上正常)。

但是,当我检查 member2 的内存布局时,我可以看到该成员附加了 4 个填充字节。 谁能解释为什么member2 接收填充字节?我的期望是member2 没有填充。


编辑 1: 请参阅此内存转储。在填充结构元素之前,我已经 memset'd 整个 t_outer 结构与 p's:

  • 红色区域为member1
  • 蓝色区域为member2
  • 绿色区域为member3
  • 黄色区域标记dbl1member3内的位置


约束

  • 编译器为VS2012
  • other_struct 的实际结构在这里应该无关紧要,它是一个 40 字节大小的 4 字节对齐结构
  • 我确实想要该行为的任何解决方法(重新排序、打包等),但要解释为什么会发生这种情况。

【问题讨论】:

  • 什么是“other_struct”?
  • 填充由编译器自行决定插入,那么你使用的是哪个编译器?
  • 你能澄清填充在哪里吗?在 member2 之前或之后。

标签: c windows memory alignment padding


【解决方案1】:

VS2012 文档describe its padding behavior。特别是,他们指定struct 的对齐要求是其任何成员的最大对齐要求。成员 member3 的类型 t_inner 具有类型为 double 的成员,具有 8 字节对齐要求,因此 member3 总体具有 8 字节对齐要求(并且,t_outer 也具有 8 -字节对齐要求)。在member2member3 之间需要填充以获得member3 的8 字节对齐。

【讨论】:

  • 听起来很合理。 t_outermember3的8字节对齐不影响member1的对齐,对吧?
  • 嗯,member1 没有 直接 含义,但因为它是 t_outer 的第一个成员,t_outer 需要 8 字节对齐,VS2012 布局声明顺序中的成员,member1 将始终在 8 字节边界上对齐。
【解决方案2】:

这样 dbl1 在 8 字节边框上对齐

当然。但是,如果结构本身也未与 8 对齐,则该对齐保证意味着 bupkis。这是通常编译器为数据段和堆栈帧的地址选择提供的保证。或者内存分配器。都保证至少与 8 对齐。

但是,当您将结构嵌入到 s_outer 中时,需要在 member3 之前(而不是在 member2 之后)填充这 4 个字节的 字节。

另请注意,结构可以在最后一个成员之后进行填充。当结构存储在数组中时,可能需要确保成员仍然对齐。同样的原因。

【讨论】:

  • 感谢您的澄清。一个插件:之后的绿色区域似乎不再对齐。我假设对齐必须保持为 8,直到结构的所有双精度都被读取,然后弹出到 4。这是正确的吗?
  • 不明白你的意思,看起来与我一致,我只看到一个双倍。我们看不到“fourth_struct”。
  • “我假设对齐必须保持为 8,直到结构的所有双精度都被读取,然后弹出到 4。这正确吗?”不,这是不正确的。 VS 文档实际上并没有精确地指定该区域的行为,但给定了一系列 doubleintintdouble 类型的成员,它与第二个 @ 的 VS 文档一致987654326@ 在 4 字节边界上对齐(这就是我预测它对齐的方式)。
  • @JohnBollinger:我在这个问题上提出了一个新问题:stackoverflow.com/q/27858493/520162
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
  • 2012-05-01
  • 2016-01-13
相关资源
最近更新 更多