简体   繁体   English

C++ ODR 违规和共享库

[英]C++ ODR violation and shared libraries

Let's say we have a program that is statically linked against MyLib1.0.假设我们有一个静态链接到 MyLib1.0 的程序。 Also there is a shared library which is linked against MyLib1.1.还有一个与 MyLib1.1 链接的共享库。

Now what happens if the program loads this shared library?现在如果程序加载这个共享库会发生什么? My assumption is that during runtime we will have multiple different definitions of the same symbols.我的假设是在运行时我们将对相同的符号有多个不同的定义。

Does both of the following scenarios violates ODR?以下两种情况是否都违反了 ODR?

  1. Shared lib exports all the symbols including the symbols of MyLib1.1共享库导出所有符号,包括MyLib1.1的符号
  2. Shared lib hides every symbols of MyLib1.1共享库隐藏了MyLib1.1的所有符号

Does it matter at all if shared lib is dynamically linked or dynamically loaded?动态链接或动态加载共享库是否重要?

There are some similar questions but I couldn't find a very clear answer so far.有一些类似的问题,但到目前为止我找不到非常明确的答案。

From the point of view of the ISO C++ standard which defines the "one-definition-rule" there is no concept of static or dynamic linking.从定义“单一定义规则”的 ISO C++ 标准的角度来看,没有 static 或动态链接的概念。 There are only translation units.只有翻译单位。

If your program contains translation units which define the same entity in two different ways (eg because the definition changed with version 1.1 of MyLib ), then that is an ODR violation and the program has undefined behavior, irregardless of how you are linking the program.如果您的程序包含以两种不同方式定义同一实体的翻译单元(例如,因为定义随MyLib的 1.1 版而更改),那么这就是 ODR 违规,并且该程序具有未定义的行为,无论您如何链接该程序。

Everything beyond that is specific to how linking works on the given platform, although of course a lot of it is common behavior, eg shared libraries can override symbols and have symbols local to itself.除此之外的所有内容都特定于链接在给定平台上的工作方式,尽管当然其中很多是常见行为,例如共享库可以覆盖符号并具有自身的本地符号。

Compilers have flags and attributes to specify this behavior, eg GCC has the -fvisibility flag and the __attribute__((visbility(/*...*/))) attribute.编译器具有标志和属性来指定此行为,例如 GCC 具有-fvisibility标志和__attribute__((visbility(/*...*/)))属性。 Specifing that a symbol is local to the shared library doesn't imply though that it will be compatible when another version is used in the program.指定一个符号是共享库的本地符号并不意味着它在程序中使用另一个版本时是兼容的。 For example if the memory layout of a class changed between versions and an object is passed between two parts of the program using the different versions, they are likely to access memory in an incompatible manner, resulting in undefined behavior in the practical sense (rather then the standard's one).例如,如果 class 的 memory 布局在版本之间发生变化,并且 object 在使用不同版本的程序的两个部分之间传递,它们很可能以不兼容的方式访问 memory,从而导致实际意义上的未定义行为(而不是然后标准的)。

Whether a certain combination of linking different library versions works depends on a lot of factors.链接不同库版本的特定组合是否有效取决于很多因素。 So it should only be done if the library author states that this is supported.因此,只有在库作者声明支持时才应该这样做。 They need to explicitly take care that changes to the library are binary/ABI-compatible.他们需要明确注意对库的更改是二进制/ABI 兼容的。 This is already true when using headers of a different version, not only when actually linking it.当使用不同版本的标头时,这已经是正确的,而不仅仅是在实际链接它时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM