$ gcc main.o f1.o f2.o
f2.o: In function `f':
f2.c:(.text+0x0): multiple definition of `f'
f1.o:f1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
$ gcc main.o -L. -Wl,-whole-archive -lf1 -lf2 -Wl,-no-whole-archive
./libf2.a(f2.o): In function `f':
f2.c:(.text+0x0): multiple definition of `f'
./libf1.a(f1.o):f1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
不可能有编译错误,每个翻译单元中只有一个函数定义,
main完全合法。链接过程中出现问题。链接器的工作原理很简单:如果代码中仍然存在未解析的符号,它会查看可用的库并添加它找到的第一个定义。结果是一个C不包含未定义行为的程序——链接阶段所有函数的定义都被明确解析。注意:该标准认为具有多个定义的程序集是未定义的行为。在我的示例中,您获得工作程序的事实取决于特定链接器在特定操作系统中的工作方式。在正常的开发中,不应该是这样的。
插图:
训练:
结果取决于命令行上库的顺序。链接器选择第一个匹配符号而不检查它是否唯一:
您的情况有所不同:该函数
main已在其中一个目标文件和库中定义。让我们对函数做同样的事情f。链接器不查看libf2.a- 不需要:仅当两个定义都在目标文件中而不是库中时才会发生错误。链接器必须收集所有这些符号:
PS Fat-Zer提出了一种简单的方法来诊断库中的多个定义。
-Wl,-whole-archive库周围的/密钥对-Wl,-no-whole-archive导致链接器包含库中的所有符号(不仅仅是必需的符号):