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

Kir*_*rov 4 c c++ dynamic-linking multiple-definition-error static-linking

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

我做了以下测试:

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

测试2静态链接:
静态库完全相同

测试3动态加载
手动加载库时,一切都按预期工作.


我预计多个定义会出错,这显然不会发生.

此外,这不会打破单一定义规则,因为情况不同.

它也不是一个依赖地狱(不是它与此有关),也不是任何链接惨败..

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

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


相关问题:
dlopen与链接开销
动态链接和动态加载之间的区别
使用-Bsymbolic函数是否存在缺点?
为什么库链接的顺序有时会导致GCC错误?
将两个共享库与一些相同的符号链接起来


编辑我做了两个测试,证实了这个UB:

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

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

但是使用静态链接现在改变了一些事情:如果test.1之前 test.2,没有错误,test.1则会调用两个函数.
但是当订单更改时,会出现"多个定义"错误.

很明显,"不需要诊断"(参见@MarkB的答案),但有时候发生错误是"奇怪的",有时候 - 它没有.

无论如何,答案很清楚,并解释了上面的一切 - UB.

use*_*697 9

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

在您的第一组测试中,一切都很清楚:链接器满足f()第一个可用库的引用,而且几乎就是它.

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

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


Mar*_*k B 2

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

3.2/3:

每个程序都应包含该程序中使用的每个非内联函数或变量的确切定义;无需诊断。