sizeof(bool)的更改真的可以破坏旧代码吗?

时间:2019-02-05 23:13:04

标签: c gcc abi

我有一个C库,使用的是这样的东西:

struct Foo {
  const char *bar;
  bool important;
  struct Baz *baz;
}

最近,我在假设importantfalse的项目中使用了它,但是它的评估结果为true。从结构的内存布局(转储)开始,我观察到(从一开始):

  • 8个非零字节
  • 1个零字节
  • 7个非零字节
  • ...

由于我的架构是x86_64,因此我认为:

  • 前8个字节是bar成员
  • 然后有一个important成员,根据设置它的代码,它的宽度应为1B(因此为1个零字节),但同时它的宽度应为4B({ {1}}),通过检查其真实性的代码(因此其评估为sizeof int
  • 然后填充到8B

如果相关的话,我的平台是带有GCC发行版(4.8.5 RedHat)的CentOS 7。


我的问题是-这真的会发生吗?毫无疑问的程序员会由于sizeof(bool)的变化而遇到ABI损坏吗?有关以下内容的其他提示:

  • 如何测试(MWE)
  • 哪个版本的GCC / glibc / C标准带来了这一变化
  • 如何避免

不客气。

1 个答案:

答案 0 :(得分:4)

  

改变sizeof(bool)真的可以破坏旧代码吗?

是的。很容易找到错误地假设 的代码,这些代码与bool的大小和(缺少)填充有关。

  

...有一个important成员,根据设置它的代码,该成员的宽度应为1B(因此为1个零字节),但同时它的宽度也应为4B (sizeof int

即使代码是C99之前的版本,代码定义类型bool的大小也应该是sizeof(bool)或更好,struct Foo f; sizeof(f.important)而不是sizeof int。 / p>

此外,尽管代码未显示如何应用这些大小,但另一个问题是填充。布局本来可以

8 byte pointer,  1 byte bool, 7 padding
8 byte pointer,  4 byte bool, 0 padding
8 byte pointer,  4 byte bool, 4 padding
4 byte pointer,  1 byte bool, 3 padding
2 byte pointer,  4 byte bool, 0 padding
etc.

更好的代码本来会使用offsetof()来查找偏移量,而使用sizeof(object.member)来查找大小。