gcc在静态库中链接未解析符号的顺序是什么
当调试函数符号冲突问题时,我发现gcc的一个奇怪的行为我无法理解,通过以下示例代码说明:
main.c中
#include int main() { b(); a(); }
AC
#include void a(void) { printf("func a in a\n"); }
公元前
#include void a() { printf("func a in b\n"); } void b() { printf( "func b try to call a \n"); a(); }
编译:
gcc -c ac gcc -c bc ar -cr liba.a ao ar -cr libb.a bo gcc main.c liba.a libb.a
执行:
./a.out func b try to call a func a in b func a in b
我的问题是:
- 为什么在
main
函数中调用函数a
是a in bc
而不是a in ac
? - 更改库顺序后:
gcc main.c libb.a liba.a
,结果是一样的。 为什么? - 为什么链接器在这种情况下不报告符号冲突?
在传递给链接器的选项中,按从左到右的目标文件外观的顺序搜索目标文件中要解析的符号。
假设以下内容已经准备好连接:
gcc -c main.c gcc -c ac gcc -c bc ar -cr liba.a ao ar -cr libb.a bo
然后这个
gcc -o main main.o liba.a libb.a
会产生:
libb.a(bo): In function `a': bc:(.text+0x0): multiple definition of `a' liba.a(ao):ac:(.text+0x0): first defined here collect2: ld returned 1 exit status
链接器执行以下操作:
main.o
需要a()
和b ()
。 搜索第一个liba
:找到b()
, b()
不是。 所以其次是搜索libb
。 找到b()
,但另一个 a()
导致上面显示的链接器错误。
如果做:
gcc -o main main.o libb.a liba.a
没有给出错误并且创建了main
。
链接器执行以下操作:
main.o
需要a()
和b ()
。 搜索第一个libb
:找到a()
和b()
。 因为没有什么可以解决的,所以libb
liba
甚至没有被查看/在。
在后一种情况下,程序的( main
)输出是:
func b try to call a func a in b func a in b
链接器将对main.o
, liba.a
和libb.a
所有其他可能的排列执行/显示的内容留给读者作为练习。 😉
您没有在main.c
包含a
和b
函数声明。 如果这样做,在传递给链接器之前,您将从编译器获得多个声明错误。 你必须在main.c
做错事。