为什么链接器链接了错误的函数?
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 使用完全不同的名称。
我对以下情况很困惑:
我有 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 使用完全不同的名称。