【问题标题】:Same symbols in different libraries and linking order不同库中的相同符号和链接顺序
【发布时间】:2015-05-18 17:44:52
【问题描述】:

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

我做了以下测试:

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

测试 2 静态链接:
静态库也是如此

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


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

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

这也不是一个依赖地狱(根本不与此相关),也不是任何链接惨败..

那么,这是什么?未定义的行为?未指定的行为?还是真的取决于链接顺序?

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


相关问题:
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之前 test.2,则没有错误,来自test.1 的两个函数都被调用。
但是当顺序改变时,会出现“多重定义”的错误。

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

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

【问题讨论】:

  • /me 认为您应该检查此行为的标准是 ELF 标准,而不是 C++ 标准。

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


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    这绝对违反了案例 1 和 2 中的单一定义规则。在第 3 种情况下,由于您明确指定要执行的函数的版本可能会也可能不会。违反 ODR 是未定义的行为,无需诊断。

    3.2/3:

    每个程序都应包含每个非内联的确切定义 在该程序中使用 odr 的函数或变量;没有诊断 必填。

    【讨论】:

    • Hm.. 现在我不知道为什么以及如何决定这不会破坏 ODR.. 但它仍然困扰我为什么没有错误,因为链接器清楚地看到了这两个这种情况下的定义(不是必须的,但仍然如此)。那么,如果这些函数不是全局的,而是一些“内部”的,-Bsymbolic“解决”了这个?
    • ODR 是编译器的规则,为什么会和链接有关?
    猜你喜欢
    • 1970-01-01
    • 2014-12-11
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多