假设我有一个如下所示的编译行:
gcc <flags...> -o a.out obj1.o obj2.o
其中 和obj1.o
都obj2.o
定义void f(int)
. 我将收到多重定义错误(违反了单一定义规则)。
好的,现在,想象一下:
gcc <flags...> -o a.out obj1.o -lstatic_lib
其中 和obj1.o
都static_lib.a
定义f(int)
. 我知道静态库是.o
文件的串联,对于每个待解决的符号,都可以在.o
静态库的任何文件中找到,然后解析该符号的整个 .o
符号将与任何符号一起链接到二进制文件中同样.o
提供的其他符号。
这种行为让我感到好奇。想象一下static_lib.a
由两个对象组成,static_obj1.o
并且static_obj2.o
,其中static_obj1.o
是由谁定义的f(int)
。由于也obj1.o
已定义f(int)
,因此链接器不会在 中查找它static_lib.a
,因此static_obj1.o
理论上不会包含在内,但是,这就是问题:
- 如果
obj2.o
需要f2(int)
,谁也定义了呢static_obj1.o
?链接器在集成后是否会static_obj1.o
因为现在是两次f2(int)
而发出多重定义警告f1(int)
?
注意:我同时标记了 C 和 C++,因为我猜想两者在这方面的行为是相同的。如果不是,请澄清,我很想知道任何行为差异。另外,如果 gcc/clang/visual studio/linux/windows 之间的行为有很大不同,请澄清。如果行为大致相同,那么重点关注 gcc 而不是 linux。
是的。
这不受 C++ 中的单定义规则或 C 中的相应规则的约束。关于此链接问题,这些规则仅表明符合要求的程序不会包含多个定义。它们不控制与多个定义链接时发生的情况。例如: