C
假设我有以下 C 模块:
MODULE 1
#include <stdio.h>
int x;
int main(){
foo();
printf("%i\n",x);
return 0;
}
MODULE 2
double x;
void foo(){
x = 3.14;
}
我的问题是:在这种情况下链接器会做什么?在我读的教科书中,它说编译器只为链接器符号表选择两个弱全局变量之一。这两个选择哪个?还是两者都选择了?如果是这样,为什么?谢谢。
C 说这是未定义的行为。
(C99, 6.9p5) “如果在表达式中使用使用外部链接声明的标识符(而不是作为结果为整型常量的 sizeof 运算符的操作数的一部分),则在整个程序中的某处应该恰好有一个外部链接标识符的定义;否则,不得超过一个”
未定义的行为意味着链接器可以在存在多个外部对象定义的情况下中止链接过程。
现在链接器很好(或者evil,您可以选择)并且通常具有默认扩展来处理多个外部对象定义并且在某些情况下不会失败。
如果您正在使用gcc
and ld
从 binutils 中,如果您的两个对象被显式初始化,您将收到错误。例如,你有int x = 0;
在第一个翻译单元中和double x = 0.0;
.
否则,如果外部对象之一未显式初始化(您示例中的情况)gcc
会默默地将两个对象组合成一个符号。您仍然可以通过向链接器传递选项来要求链接器报告警告--warn-common
.
例如链接模块时:
gcc -Wl,--warn-common module1.o module2.o
要中止链接过程,您可以使用以下命令请求链接器将所有警告视为错误--fatal-warnings
选项 (-Wl,--fatal-warnings,--warn-common
).
中止链接过程的另一种方法是使用-fno-common
编译器选项,如所解释的@teppic https://stackoverflow.com/users/1627348/teppic在他的回答中。-fno-common
禁止外部对象在编译时获取通用符号类型。如果您对两个模块都执行此操作然后链接,您还会收到多重定义链接器错误。
gcc -Wall -fno-common -c module1.c module2.c
gcc module1.o module2.o
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)