关于GCC链接器搜索顺序的一些问题

时间:2012-05-14 14:22:42

标签: linux gcc linker shared-libraries static-libraries

我对gcc链接顺序有一些疑问。 GCC man表示链接器从左到右搜索符号,默认情况下不重复搜索。这是我的测试:

的main.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
        printf("HELLO WROLD\n");
        return 0;
}

printf.c

#include <stdio.h>
#include <stdlib.h>

int printf(const char *fmt, ...)
{
        write(1, "AAA\n", 4);
}

[root@lenovo testcode]# gcc -c -fno-builtin-printf *.c
[root@lenovo testcode]# gcc -o test main.o printf.o
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test printf.o main.o
[root@lenovo testcode]# ./test
AAA


[root@lenovo testcode]# ar rcs libprintf.a printf.o
[root@lenovo testcode]# gcc -o test libprintf.a main.o
[root@lenovo testcode]# ./test 
HELLO WROLD
[root@lenovo testcode]# gcc -o test main.o libprintf.a 
[root@lenovo testcode]# ./test 
AAA


[root@lenovo testcode]# gcc -shared -o libprintf.so printf.o 
[root@lenovo testcode]# gcc -o test libprintf.so  main.o 
[root@lenovo testcode]# export LD_LIBRARY_PATH=.
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test main.o libprintf.so 
[root@lenovo testcode]# ./test 
AAA

从结果中,我们可以看到.o和.o,.o和.so的顺序没有区别,只有.o和.a的顺序才有效。但这与gcc手册页不一致。那为什么呢?

1 个答案:

答案 0 :(得分:8)

gcc确实从左到右处理目标文件。当你有

gcc -o test libprintf.a main.o

gcc看到的第一个目标文件是libprintf.a。此时输出对象没有未解析的符号,因此使用/需要libprintf.a的任何内容。接下来,处理main.o,链接器记录printf未解析的事实,然后继续处理隐式库,它可以解析printf符号未解决的in main.o

同样,当你有:

gcc -o test main.o libprintf.a 

要处理的第一个目标文件是main.o,其中注明了未解析的符号printf,下一个要处理的是libprintf.a,链接器可以从中解析printf {{ 1}}。最终处理libc时,printf已经解决,因此printflibc的实例未被使用。

与.o文件链接时:

gcc -o test main.o printf.o

libc库再次被视为在命令行末尾指定,因此printf符号从定义的第一个(从左到右)对象文件中解析它

对于两个libprintf.so个案例,libc库再次被视为在命令行末尾指定它。与静态库案例的不同之处在于*.so库的从左到右排序决定了运行时动态符号搜索顺序。由于此订单在隐式libprintf.so之前有libc.so,因此会使用printflibprintf.so的版本。

gcc -o test libprintf.so  main.o
gcc -o test main.o libprintf.so

作为额外的实验,您可以尝试:

gcc -o test main.o -lc libprintf.so

这应该显示printf使用的libc.so版本,而不是libprintf.so,因为-lc按照从左到右的顺序出现在libprintf.so之前。