在调试函数符号冲突问题时,我发现gcc的一个奇怪行为我无法理解,下面的示例代码举例说明:
main.c
#include <stdio.h>
int main()
{
b();
a();
}
a.c
#include <stdio.h>
void a(void)
{
printf("func a in an");
}
b.c
#include <stdio.h>
void a()
{
printf("func a in bn");
}
void b()
{
printf( "func b try to call a n");
a();
}
编译:
gcc -c a.c
gcc -c b.c
ar -cr liba.a a.o
ar -cr libb.a b.o
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 b.c
而不是a in a.c
- 更改库顺序:
gcc main.c libb.a liba.a
后,结果相同。为什么 - 为什么链接器在这种情况下不报告符号冲突
在传递给链接器的选项中,按对象文件的出现顺序从左到右搜索要解析的符号。
假设在准备链接时运行了以下内容:
gcc -c main.c
gcc -c a.c
gcc -c b.c
ar -cr liba.a a.o
ar -cr libb.a b.o
然后这个
gcc -o main main.o liba.a libb.a
将产生:
libb.a(b.o): In function `a':
b.c:(.text+0x0): multiple definition of `a'
liba.a(a.o):a.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
链接器执行以下操作:
CCD_ 6需要CCD_ 7和CCD_。搜索第一个liba
:找到了a()
,没有找到b()
。其次搜索CCD_ 12。发现了b()
,但也另一个a()
导致了上面显示的链接器错误。
如果进行:
gcc -o main main.o libb.a liba.a
没有给出任何错误,并且创建了main
。
链接器执行以下操作:
CCD_ 16需要CCD_ 17和CCD_。搜索第一个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
中做错了什么。