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函数中调用函数aa 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.oliba.alibb.a所有其他可能的排列执行/显示的内容留给读者作为练习。 😉

您没有在main.c包含ab函数声明。 如果这样做,在传递给链接器之前,您将从编译器获得多个声明错误。 你必须在main.c做错事。