c++ - 不同库中的相同符号和链接顺序

标签 c++ c static-linking dynamic-linking multiple-definition-error

我有 2 个库:test.1test.2。这两个库都包含一个全局 extern "C" void f(); 函数,具有不同的实现(只是一个用于测试的 cout)。

我做了以下测试:

测试 1 动态链接:
如果我在可执行文件的 makefile 中添加 libtest.1.so 然后 libtest.2.so 然后调用 f(); main, libtest.1.so->f() 被调用。
如果我更改 makefile 中的顺序,将调用 libtest.2.so->f()

测试 2 静态链接:
静态库完全一样

测试3动态加载
由于库是手动加载的,所以一切都按预期进行。


我预计多个定义会出现错误,但这显然没有发生。

此外,这并没有打破单一定义规则,因为情况不同。

它也不是依赖 hell (与此无关),也不是任何链接失败..

那么,这是什么?未定义的行为?未指定的行为?或者它确实取决于链接顺序?

有没有办法轻松检测到这种情况?


相关问题:
dlopen vs linking overhead
What is the difference between dynamic linking and dynamic loading
Is there a downside to using -Bsymbolic-functions?
Why does the order in which libraries are linked sometimes cause errors in GCC?
linking two shared libraries with some of the same symbols


编辑 我又做了两次测试,确认了这个 UB:

我在 test.1 中添加了第二个函数 void g() 而不是在 test.2 中。

使用动态链接和 .so 库,会发生同样的情况 - f 以相同的方式调用,g 也是可执行的(如预期)。

但是现在使用静态链接改变了事情:如果 test.1 before test.2,没有错误,两个函数来自 test.1 被调用。
但是当顺序改变时,出现“多重定义”错误。

很明显,“不需要诊断”(请参阅​​@MarkB 的回答),但有时会发生错误,有时却不会,这很“奇怪”。

无论如何,答案很清楚并解释了上面的所有内容 - UB。

最佳答案

库是目标文件的集合。链接器根据需要从库中提取对象以满足未解析的符号。重要的是,链接器按照它们在命令行中出现的顺序检查库,只检查每个库一次(除非命令行不止一次提到该库),并且只接受满足某些引用的对象。

在您的第一组测试中,一切都很清楚:链接器满足来自第一个可用库的对 f() 的引用,仅此而已。

现在是第二组测试。在成功案例中,test.1 满足 fg 引用,因此 test.2 是无关紧要的。在失败的情况下,test.2 满足 f 引用,但 g 仍未定义。为了满足 g,链接器必须从 test.1 中提取一些对象,它也恰好提供 f。显然是多重定义。

请注意,为了避免错误,您必须在同一对象中包含 fg。如果 test.1 由 2 个对象组成(一个定义 f,另一个定义 g),则错误消失。

关于c++ - 不同库中的相同符号和链接顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29079742/

相关文章:

c++ - 函数不能用作 'constexpr' 函数

c++ - 通过引用传递的函数接受对带有operator()的类的引用

C++ 和 box2d : userdata cast int to void*

c - 错误结果 : time(NULL) and clock()

c - 为什么这个 shellcode 程序会发出段错误警告?

c++ - 使用-static的 undefined reference ?

c++ - 用于在 C++ 中组合多个非常大的栅格数据文件的 STL 容器

c - 在具有相同类型成员的结构上使用 free

c++ - 静态库缺少 `__imp_` 符号

linker - d2 : importing function from external library under different name it was originally exported