为什么链接器链接了错误的函数?

Why wrong function was linked by the linker?

我对以下情况很困惑:

我有 Linux 项目(用 c 语言编写)使用静态库 A 来获取可执行文件。在这个静态库 A 中,有一个 c 代码从 Linux include 调用 sem_init。 .c文件中有include to semaphore.h,使用GCC编译的文件没有警告。我使用 ld 链接器。

一切都很好,直到我无意中向项目添加了一个新模块(编译到静态库 B)。新代码具有同名 (sem_init) 但签名不同的函数。来自 A 的代码不包括来自 B 的定义新 sem_init() 的 .h 文件。

现在,在将库 B 添加到编译后,我看到 sem_init 不是来自 semaphore.h,而是从库 B 调用了新的 sem_init。

我知道调用同名函数是个糟糕的主意,但在大型项目中,它可能会无意中发生。

问题:为什么会这样???为什么链接器选择了新的 sem_init???为什么我没有收到多重定义链接错误?

当链接器链接静态库时,它只在此处查找未定义的符号,如果找到定义,则将其链接并解析该符号。 sem_init 恰好来自 B,它在 -lc 之前被链接(GNU C 标准库也实现了 POSIX sem_init)被链接,因此链接器从 B 中获取 sem_init 然后再也不会寻找 sem_init,这就是为什么你没有得到多个符号定义错误的原因。

B 库可能不打算使用不同的参数列表来实现 POSIX sem_init。它可能需要将其 sem_init 标记为 static 以便其他翻译单元看不到它。 And/or 使用完全不同的名称。