我有几个关于gcc链接顺序的问题。GCC说,默认情况下,链接器从左到右搜索符号,不重复搜索。这是我的测试:
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手册页不一致。那为什么呢?
发布于 2012-05-15 00:27:12
gcc确实是从左到右处理目标文件的。当你有了
gcc -o test libprintf.a main.ogcc看到的第一个对象文件是libprintf.a。此时,输出对象没有未解析的符号,因此不使用/需要来自libprintf.a的任何内容。接下来,处理main.o,链接器记下printf未解析的事实,然后继续处理隐式库,在隐式库中,它能够解析未解析的printf符号in main.o。
同样,当你拥有:
gcc -o test main.o libprintf.a 第一个要处理的目标文件是main.o,其中记录了未解析的符号printf,下一个要处理的目标文件是libprintf.a,链接器可以从中解析printf。当libc最终被处理时,printf已经被解析,所以libc中的printf实例不会被使用。
当链接到.o文件时:
gcc -o test main.o printf.o再次将libc库视为在命令行末尾指定的库,因此将从定义它的第一个(从左到右)对象文件解析printf符号。
对于这两种libprintf.so情况,libc库再次被视为是在命令行末尾指定的。与静态库的情况不同的是,*.so库的从左到右的顺序决定了运行时动态符号搜索的顺序。由于此订单在隐式libc.so之前具有libprintf.so,因此使用libprintf.so中的printf版本。
gcc -o test libprintf.so main.o
gcc -o test main.o libprintf.so作为额外的实验,您可以尝试:
gcc -o test main.o -lc libprintf.so这应该会显示从libc.so使用的printf版本,而不是libprintf.so,因为-lc按从左到右的顺序在libprintf.so之前。
https://stackoverflow.com/questions/10585225
复制相似问题