不同库和链接顺序中的相同符号 [英] Same symbols in different libraries and linking order

查看:180
本文介绍了不同库和链接顺序中的相同符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have 2 libraries: test.1 and test.2. Both libraries contain a single global extern "C" void f(); function, with different implementations (just a cout for the test).

我做了以下测试:

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

Test 1 Dynamic linking:
If I add libtest.1.so and then libtest.2.so in the makefile of the executable and then call f(); in main, libtest.1.so->f() is called.
If I change the order in the makefile, libtest.2.so->f() is called

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

Test 2 Static linking:
Absolutely the same happens with static libraries

测试3 动态加载
手动加载该库后,一切都会按预期进行.

Test 3 Dynamic loading
As the library is manually loaded, everything works as expected.

我期望多个定义出现错误,但显然没有发生.

I expected an error for multiple definitions, which obviously didn't happen.

此外,由于情况不同,这不会违反一定义法则.

Also, this does not break the one-definition-rule, as the situation is different.

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

It's also not a dependency-hell(not that it's related to this at all), nor any linking fiasco..

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

So, than what is this? Undefined behavior? Unspecified behavior? Or it really does depend on the linking order?

有没有一种方法可以轻松检测到这种情况?

And is there a way to easily detect such situations?

相关问题:
dlopen与链接开销
动态链接和动态加载之间有什么区别
使用-Bsymbolic-functions是否有不利之处?
为什么链接库的顺序有时会导致GCC错误?
用两个相同的符号链接两个共享库

Related questions:
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:

EDIT I did two more tests, which confirm this UB:

我在test.1中添加了第二个功能void g(),而在test.2中未添加.

I added a second function void g() in test.1 and NOT in test.2.

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

Using dynamic linking and .so libs, the same happens - f is called with the same manner, g is also executable (as expected).

但是现在使用静态链接会改变情况:如果test.1之前 test.2,则没有错误,将调用test.1中的两个函数.
但是,当顺序更改时,会出现多个定义"错误.

But using static linking now changes the things: if test.1 is before test.2, there are no errors, both functions from test.1 are called.
But when the order is changed, "multiple definitions" error occurs.

很明显,不需要诊断"(请参阅​​@MarkB的答案),但是有时会发生错误,有时却不会,这是奇怪的".

It's clear, that "no diagnostic required" (see @MarkB's answer), but it's "strange" that sometimes the error occurs, sometimes - it doesn't.

无论如何,答案很明确,并解释了上面的所有内容-UB.

Anyway, the answer is pretty clear and explains everything above - UB.

推荐答案

在案例1和案例2中,这绝对违反了一个定义规则.在情况3中,由于您显式指定了执行该功能的版本,因此可能会执行,也可能不会执行.违反ODR是未定义的行为,不需要诊断.

This absolutely violates the one definition rule in cases 1&2. In case 3, since you explicitly specify which version of the function to execute it may or may not. Violating the ODR is undefined behavior, no diagnostic required.

3.2/3:

每个程序应仅包含每个非内联的一个定义 该程序中常用的函数或变量;没有诊断 必填.

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

这篇关于不同库和链接顺序中的相同符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆