我对 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 手册页不一致。所以为什么?
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
. When libc
最终被处理,printf
已经解决了,所以实例printf
in libc
未使用。
与 .o 文件链接时:
gcc -o test main.o printf.o
The libc
库再次被视为在命令行末尾指定,因此printf
符号是从定义它的第一个(从左到右)目标文件解析的。
对于这两个libprintf.so
案例中,libc
库再次被视为在命令行末尾指定。与静态库情况不同的是,从左到右的顺序*.so
库决定运行时动态符号搜索顺序。由于该订单已libprintf.so
在隐式之前libc.so
,版本printf
in libprintf.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
按从左到右的顺序。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)