【问题标题】:struct storage size error not reported by GCC with optimization turned onGCC 未报告结构存储大小错误,优化已打开
【发布时间】:2015-07-16 19:25:39
【问题描述】:

在一个文件 struct_test.c 我写:

static struct x x; 

我使用 GCC(4.8.2,Ubuntu)进行编译

gcc -c -O0 struct_test.c

我得到了可以理解的错误:

error: storage size of 'x' isn't known

然后我重新编译,这次开启了优化

gcc -c -O struct_test.c

并且文件编译没有错误。

我可以理解为什么打开优化会消除错误,但有人可以帮助我获得指示 gcc 忽略未定义标记“x”的实际编译器选项吗?

【问题讨论】:

  • 发布MCVE 应该是微不足道的(强调完整)。这样做。
  • 你在任何地方都使用x吗?优化器是否可以删除未使用的声明,因此它不会抱怨它不知道大小?
  • @TripeHound 当然,我没有在任何地方使用“x”。我想了解的是哪些编译器选项指示优化器忽略未使用的声明。
  • 您要查找的选项是-fdce(死代码消除),它是-O 的一部分。
  • @fsheikh 真奇怪。您说您收到未使用的 var 警告,但没有关于暂定声明警告/错误? gcc 必须表现出额外的迂腐水平。 gcc 肯定有可能没有这样的警告/错误,并且不会在链接时为错误而烦恼,因为无论如何 var 都会被 opti 绊倒(您现在可能看到的内容)。上升。

标签: c gcc struct compiler-optimization


【解决方案1】:

当它出现在文件范围内时,这段代码:

static struct x x;

x 声明为struct x 类型的对象并具有内部链接。 struct x 类型不需要事先声明:

如果struct-or-union identifier 形式的类型说明符出现在 [在结构类型声明中] 之外,并且没有其他作为标记的标识符声明可见,则它声明不完整的结构或联合类型,并声明标识符作为该类型的标记。

(C99 6.7.2.3/8)

在翻译单元中第一次遇到不完整的结构或联合类型,但稍后可以在该翻译单元中完成:

未知内容的结构或联合类型 [...] 是不完整类型。对于该类型的所有声明,它是通过稍后在相同范围内声明相同的结构或联合标记及其定义内容来完成的。

(C99 6.2.5/22)

C 通常区分“声明”和“定义”,“声明”指定对象的类型,“定义”指定类型并导致存储被保留。在给定的翻译单元中,不是定义的声明可能具有在该单元内从不完成的不完整类型。

C99 的第 6.9.2 节指定哪些文件范围对象声明是定义:

  • 具有文件范围和初始化程序的声明是一个定义(特别是“外部定义”,即使它定义的对象可能具有内部链接)
  • 具有文件范围且没有初始化程序的声明,以及具有静态存储类或没有存储类说明符的声明是“暂定定义”。如果翻译单元不包含同一对象的外部定义,则行为就像存在具有初始化程序 0 的外部定义一样。

本节还规定“如果对象标识符的声明是暂定定义并具有内部链接,则声明的类型不应是不完整的类型。”这适用于这里,但是由于翻译单元中某一点不完整的类型可以通过稍后的声明来完成,因此它不会固有地使相关代码行无效。但是,它确实使仅包含该行的翻译单元无效。

那么 GCC 是怎么回事?

由于给出的代码,作为一个完整的翻译单元,违反了“不得”的语言约束,它会产生未定义的行为。 GCC 没有义务拒绝代码或产生任何类型的诊断,尽管它被允许做一个或两个。事实证明,无论优化级别如何,如果 -Wall-pedantic 标志打开,gcc 确实会发出有关代码的警告。不管怎样,gcc 明确否认自己是验证代码是否符合标准的工具。

然而,这种特殊的违规行为是相对温和的。因为该对象从未被引用,gcc 可以假装它从未被声明过,而不会冒错误或意外行为的风险。

-fdce(死代码消除)选项似乎是影响此特定行为的选项。奇怪的是,虽然-fdce 足以抑制优化级别 O0 的错误,但 -fno-dce 并没有在更高的优化级别将其带回。

【讨论】:

  • 非常感谢您的全面回答。非常感谢!
  • 由于这是规范中的“不得”要求,因此违反它的程序会导致未定义的行为——这意味着不需要符合标准的编译器来诊断任何内容,并且可以做任何事情(包括简单地忽略它,就像 gcc 在这里所做的那样)。
  • 谢谢,@ChrisDodd。根据您的观察,我修改了我的 cmets 的最后一部分。
猜你喜欢
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 2012-09-26
  • 2015-10-22
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多