当 extern 声明和定义之间的类型不匹配时,会有什么行为?
假设我有两个文件:
==文件1==
extern char* foo;
==文件2==
double foo;
尽管类型不匹配,这两个文件似乎与 g++ 和 clang++ 都可以很好地编译和链接.据我了解,推荐的做法是将 extern 声明放在两个文件都包含的标头中,因此 File2 将引发重新定义错误.
These two files seem to compile and link just fine with both g++ and clang++ despite the type mismatch. As I understand it the recommended practice is to put the extern declaration in a header which both files include so File2 will throw a redefinition error.
我的问题是:
- 根据 c++ 标准,这是否会导致未定义的行为?如果不是 File1 中的 foo 中的内容是什么?
- 链接器能否捕捉到这种类型不匹配?
推荐答案
根据 c++ 标准,这是否会导致未定义的行为?
Does this result in undefined behavior according to the c++ standard?
好吧,真正的问题是这是否是未定义的行为,或者它是否被标准指定为格式错误(用标准用语).因为,显然,这是不正确的.我试图从标准中找到一些关于此的内容,但无济于事.然而,在许多类似的情况下,例如 decl/def 不匹配或在链接器中抛出一些奇怪的东西(参见第 3.5、7.5 节,或搜索extern"或linkage"),标准通常会说:
Well, the real question is whether this is undefined behavior or whether it is specified by the standard as being ill-formed (in standard parlance). Because, obviously, it is not correct. I have tried to find something from the standard about this, but to no avail. However, in a number of similar situations, e.g., mismatches of decl/def or throwing funky things at the linker (see section 3.5, 7.5, or search for "extern" or "linkage"), the standard generally ends up saying:
程序格式错误,无需诊断.
The program is ill-formed, no diagnosis required.
所以,我敢打赌,假设这里也是这种情况是非常安全的.这意味着这是错误的代码,比未定义的行为"更糟糕,因为 UB 通常会对特定的实现有某种合理的行为(尽管你不应该推测这种行为会是什么,当然也不应该依赖那个推测).格式错误"一词在标准中使用得非常随意,您可以或多或少地推断出它意味着代码是 FUBAR.这也意味着根据标准,链接器不需要以允许它捕获此类错误的方式实现,这就是它正确编译和链接的原因,但在你运行它时请抓住你的袜子.
So, I would bet it's pretty safe to assume this is the case here too. This would mean that this is erroneous code, worst than "undefined behavior", since UB often will have some kind of reasonable behaviour for a specific implementation (although you shouldn't speculate on what that behaviour would be, and certainly not rely on that speculation). The "ill-formed" term is used very liberally in the standard, and you can more or less infer that it means that the code is FUBAR. This would also mean that the linker is not required, by the standard, to be implemented in a way that allows it to catch this kind of error, and that's why it compiles and links correctly, but hold on to your socks when you run it.
链接器能否捕捉到这种类型不匹配?
Could linkers catch this kind of type mismatch?
理论上,是的.链接器实现可以将变量的类型编码(使用名称修饰)到其外部符号中,因此能够限制与类型匹配的事物的链接(例如,重载函数),或者在发生时抛出诊断(错误)它遇到类型不匹配.我认为与标准相比,前者过于宽松.
In theory, yes. A linker implementation could encode (with name-mangling) the type of the variable into its external symbol, and thus be able to either restrict linkage to things whose types match (e.g., like overloaded functions), or throw a diagnosis (error) when it encounters a mismatch in types. I think that the former would be too permissive as compared to the standard.
但是,我所知道的所有编译器都不会破坏变量的名称,因此,您可以假设这种不匹配是格式错误,不需要诊断".
However, all compilers that I know of do not mangle the names of variables, and thus, you can assume that such a mismatched is "ill-formed, no diagnosis required".
相关文章