【问题标题】:how do I choose desired symbol when linking 2 different versions of the same library?链接同一库的 2 个不同版本时如何选择所需的符号?
【发布时间】:2017-03-09 18:18:48
【问题描述】:

背景: 我正在尝试提供一个包装在接口中的库,以在第三方应用程序 (MATLAB) 中使用。 我的问题是我的库和第三方应用程序都依赖于 Boost 库。

更糟糕的是,它们不仅依赖于两个不同版本的 Boost,而且我的库是针对 Boost 的补丁版本构建的,并且它们是静态链接的。相反,第三方库是针对 Boost 动态链接的。

这就是我链接的方式(make -n 的简化输出)

g++ -fPIC ${CPPFLAGS} -shared -lc -ldl ... -Wl,-h,mylib.so -o mylib.so \
${MYSTATICLIBS} \
-L${MATLABLIBSPATH} -lmx -lmex \
-L${MYBOOSTVERSIONPATH} -lboost_thread-gcc49-mt-1_52 ...

然后,当我在 MATLAB 中运行库 fron 时,从我的内部函数调用了错误的 boost 函数(并且一切都崩溃了)。

我的直觉是,因为我静态链接了我的 Boost,所以从我的库中对它们的所有调用都应该指向我的 Boost,而来自 libmx.so 或 libmex.so 的调用将指向它们动态加载的依赖项。然而,这证明我天真的直觉是非常错误的。

我在 SO 和网络上发现了不同的提示,描述了链接顺序如何破坏类似情况,但是所有内容都描述了冲突符号的所有静态或所有动态链接。

建议的解决方案是

  • 使用 -Bsymbolic -Bsymbolic-functions
  • 将我的库升级到相同的 boost 版本
  • 更改链接顺序(首先是 boost,然后是 -lmx -lmex)
  • 卖掉我所有的尘世财产,在炎热的海滩上买一个酒吧,然后尝试以此谋生
  • 其他??

有人可以解释这些解决方案是否以及为什么有效? (我的另一个问题是,我自己无法使用 MATLAB 进行测试,因为我无法访问安装它的机器。这就是为什么我还要问“是否”提出的解决方案可行)

【问题讨论】:

  • “它们是静态链接的” - 你 100% 确定你链接到静态版本的 Boost 吗? readelf --dyn-syms -W youlib.so 的输出是否显示定义的 Boost 符号(而不是“UND”)?

标签: gcc ld elf


【解决方案1】:

首先,欢迎来到 Linux 符号插入的奇妙世界;)

我认为您的库会从与之链接的 Boost 库中导出所有符号(可以通过 readelf --dyn-syms -W 进行验证)。在运行时,动态链接器会注意到这一点,并将符号重新绑定到 不同 版本的 Boost(因为它恰好被较早加载,因此覆盖了您的库使用的符号)。

您要做的是告诉 gcc 您不想导出 Boost 符号,或者您不希望它们在运行时可插入。对此有几种解决方案,最好的方法是编译并与-fvisibility=hidden 链接(请注意,Boost 也需要与此标志链接)。这将阻止从库中导出任何函数,除非您使用__attribute__((visibility("hidden"))) 明确标记它们(当然,您需要注释库接口函数)。

另一个选项是-Bsymbolic - 这不会阻止从您的库中进行虚假的 Boost 导出,但至少可以防止动态链接器用碰巧被其他库加载的随机版本的 Boost 函数覆盖它们。

现在回答剩下的问题。

将我的库升级到相同的 boost 版本

您可以这样做,但如果 3 方在某个时候升级他们的 Boost,这可能会中断。

更改链接顺序(首先是 boost,然后是 -lmx -lmex)

没有多大意义……你试过了吗?

【讨论】:

    猜你喜欢
    • 2014-12-11
    • 2018-08-20
    • 1970-01-01
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多