我有一个与链接器密切相关的问题,当相同的符号在对象文件和静态库中共存时,它不会发出多个定义错误,但涉及的情况略有不同。 就像那里一样,我有两个.cpp文件(例如:test1.cpp
和test2.cpp
(,每个文件都包含相同功能的实现,即void testfunc()
.我还有一个头文件test.h
我在其中声明testfunc
,以及一个带有 main 函数的文件main.cpp
,其中包含对testfunc()
的调用,如下所示:
include "test.h"
int main() {
testfunc();
}
我通过调用g++ -c *.cpp
分别编译.cpp文件,然后使用ar rvs libtest.a test1.o test2.o
从中创建静态库。现在main.o
链接到库时,链接器不会像我预期的那样抱怨:
gcc main.o -L. -ltest -o main
生成的可执行文件工作得很好 - 调用testfunc()
的两个实现之一。老实说,我预计会发生一些像multiple definition of...
这样的错误。因此,我的问题是:
- 为什么这实际上有效 -
ar
中的原因,它只将两个目标文件中的一个添加到库中,或者库是否包含两个对象文件,并且这种行为的原因可以在链接过程中找到,其中链接器在找到一个定义后停止搜索库testfunc
? - 我能否以某种方式影响实际使用
testfunc
的定义,或者甚至是否定义了这个定义? 即,在决定使用哪一个ar
可能是参数的顺序吗? - 对于任何链接器/版本的
ar
,此行为是否相同,或者这可能取决于系统?
库只是包含导出符号的对象文件的集合。 它可能包含任意数量的重复项(就像真正的图书库可能包含许多具有相同标题的书籍一样(。不涉及任何链接。
链接时,一般来说,链接器仅在存在未解析的符号时查看库。 在寻找这些符号时,它可能会找到一个,如果它这样做,它将不再寻找该符号。
当它解析在另一个对象文件中找到的另一个未解析的符号时,可能会出现冲突,该文件包含先前找到的符号的定义;现在它将生成重复符号的错误。