【发布时间】:2010-12-02 05:15:42
【问题描述】:
考虑由两个文件组成的C程序,
f1.c:
int x;
f2.c:
int x=2;
我对@987654321@ 的第6.9.2 段的阅读是这个程序应该被拒绝。在我对 6.9.2 的解释中,变量 x 暂定在 f1.c 中定义,但这个暂定定义成为翻译单元末尾的实际定义,因此(在我看来)应该表现得好像 @987654326 @ 包含定义 int x=0;。
对于我能够尝试的所有编译器(以及重要的链接器),这不是发生的情况。我尝试的所有编译平台都链接了上述两个文件,两个文件中x的值都是2。
我怀疑这是偶然发生的,或者只是作为标准要求之外的“简单”功能。如果您考虑一下,这意味着链接器对那些没有初始化程序的全局变量有特殊的支持,而不是那些显式初始化为零的变量。有人告诉我,无论如何编译 Fortran 可能都需要链接器功能。这将是一个合理的解释。
对此有什么想法吗?标准的其他解释?文件f1.c 和f2.c 拒绝链接在一起的平台名称?
注意:这很重要,因为问题发生在静态分析的上下文中。如果这两个文件可能拒绝在某个平台上链接,分析器应该抱怨,但如果每个编译平台都接受它,那么没有理由警告它。
【问题讨论】:
-
感谢分享。学习永远不会太老
-
只有当你违反约束段落中的内容时,编译器才需要拒绝(即警告或错误)。您的事物可能没有两个外部定义的约束是“应”在约束段落之外。违反约束之外的任何 shall 会自动导致 C 中未定义的行为 - 这就是允许编译器按照它想要的方式对待它的原因。
-
@litb 这是一个有趣的观点。我提到的静态分析器尽可能不标记/已建立/编程实践,即使它们没有被标准定义。在这里,我认为我们将决定不发出警告,因为在不支持这些多个定义的平台上,可能它们会导致链接时失败,而不是运行时失败。 PS:我知道“未定义”是什么意思,但是每个额外的分析选项都会使分析器的可用性降低一些,并且必须权衡收益。因此,问题的“平台名称......”部分
-
最近的 gcc 版本默认使用
-fno-common。然后,即使您在f2.c中只有int x;而没有初始化,您也会收到链接器错误。恕我直言,跨编译单元合并暂定定义是不好的。它会导致错误。现在存在 extern 关键字以正确执行操作。
标签: c compilation fortran static-analysis c99