【问题标题】:Linking two shared libraries with some of the same symbols用一些相同的符号链接两个共享库
【发布时间】:2011-09-26 04:19:23
【问题描述】:

我链接了两个不同的共享库。这两个库都定义了一些共享名称但具有不同实现的符号。我不能让每个库都使用自己的实现。

例如,两个库都定义了一个全局函数bar(),每个函数都在内部调用。库一从foo1() 调用它,库二从foo2() 调用它。

Lib1.so:

T bar
T foo1()     // calls bar()

Lib2.so:

T bar
T foo2()     // calls bar()

如果我将我的应用程序与 Lib1.so 和 Lib2.so 链接,则即使在调用 foo2() 时也会调用来自 Lib1.so 的 bar 实现。另一方面,如果我将我的应用程序与 Lib2.so 和 Lib1.so 链接,则始终从 Lib2.so 调用 bar。

有没有办法让一个库总是比任何其他库更喜欢它自己的实现?

【问题讨论】:

    标签: c unix gcc shared-libraries dynamic-linking


    【解决方案1】:

    有几种方法可以解决这个问题:

    • -Bsymbolic-Bsymbolic-functions 传递给链接器。这具有全局效果:对可以解析为库中符号的全局符号(-Bsymbolic-functions 的函数类型)的每个引用都解析为该符号。这样,您就无法使用 LD_PRELOAD 对这些符号进行内部库调用。 符号仍被导出,因此可以从库外部引用它们。

    • 使用 版本脚本 将符号标记为库的 本地,例如使用类似:{local: bar;}; 并将--version-script=versionfile 传递给链接器。 符号导出。

    • 用适当的可见性 (GCC info page for visibility)标记符号,可以是隐藏内部受保护的受保护可见性符号导出为.protected隐藏符号不导出 , 和 internal 符号不会被导出,你妥协不从库外部调用它们,即使是通过函数指针间接调用。

    您可以使用objdump -T 检查导出了哪些符号。

    【讨论】:

    • 嗨,你能告诉我这是否也适用于clang吗?
    【解决方案2】:

    您必须创建两个“包装器”共享库,一个用于您现有的每个库。每个都应该使用 --dynamic-list 构建,该列表仅列出几个定义 API 的非冲突符号。您还需要 -Bsymbolic 以避免任何全局组合。

    使用合适的选项通过 dlopen 访问生成的库可能会更轻松。

    【讨论】:

    • 非常感谢!只是两个共享库链接的 -Bsymbolic 选项(使用 -Wl 选项传递给链接器)为我解决了这个问题。
    【解决方案3】:

    解决此问题的另一种方法是使用宏来更改命名空间。

    先决条件

    • 所有元素(函数、类、全局变量...)都在一个命名空间中。
    • 该库不太依赖标头中的宏。

    解决方案

    • 编译库时,使用命名空间名称定义宏以将其定义为不同的名称。例如,如果命名空间是 LibNS,则在一种情况下使用 -DLibNS=LibNSv1,在另一种情况下使用 -DLibNS=LibNSv2
    • 在代码中使用库时,根据自己的情况定义宏;

      #define LibNS LibNSv1
      #include "my_lib.h"
      #undef LibNS
      

    为什么使用这个而不是其他解决方案的原因

    • 当有问题的库(至少部分)在头文件(例如模板、内联、...)中使用时;当您将它们包含在可执行文件的代码中时,解析器不知道是应该从 Lib1.so 还是 Lib2.so 调用这些函数。
    • 您的编译器对其他解决方案的支持很差/不支持(我们的 intel/amd 32/64 位 CPU 不应该发生这种情况,但从 Google 搜索看来,其他一些平台可能存在问题)。

    潜在问题

    • 在可执行文件的一个 cpp 文件中同时使用这两个版本可能会出现问题; #include "my_lib.h" 可能使用宏来防止多重包含并取消定义它们以避免这可能会导致许多不同的问题(库作者将来可能会更改宏名称,标题定义了一些其他宏等)。
    • 名称LibNS 可能用于库中的其他内容(变量、函数等);在这种情况下,此名称也将更改为 LibNSv1LibNSv2。这可能会导致其他问题,具体取决于库及其使用方式。

    备注

    • 这并不是要替换当前接受的答案(来自 ninjalj;请随意复制粘贴),而是用另一种方法对其进行扩展。
    • 我发布这个答案的主要原因是我今天遇到了这个问题,但是由于头文件中有问题的代码,答案没有帮助。
    • 我的来源:https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-11
      • 2011-01-25
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      相关资源
      最近更新 更多