Gcc 链接同一库的两个不同版本时,如何选择所需的符号?

Gcc 链接同一库的两个不同版本时,如何选择所需的符号?,gcc,ld,elf,Gcc,Ld,Elf,背景: 我试图提供一个封装在接口中的库,用于第三方应用程序(MATLAB)。 我的问题是,我的库和第三方应用程序都依赖于Boost库 更糟糕的是,它们不仅依赖于两个不同版本的Boost,而且我的库是基于一个补丁版本的Boost构建的,它们是静态链接的。第三方库与Boost动态链接 这就是我链接的方式(简化了make-n的输出) 当我在MATLAB中运行库时,从我的内部函数调用了错误的boost函数(所有东西都崩溃了) 我天真的直觉是,由于我静态链接了Boost,所以从我的库中对它们的所有调用都应

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


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

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

当我在MATLAB中运行库时,从我的内部函数调用了错误的boost函数(所有东西都崩溃了)

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

我在这里和网上找到了不同的提示,描述了链接顺序如何打破类似的情况,然而所有的东西都描述了冲突符号的所有静态或动态链接

建议的解决办法如下:

  • 使用-b符号-b符号函数
  • 将我的库升级到相同的boost版本
  • 更改链接顺序(首先是boost,然后是-lmx-lmex)
  • 卖掉我所有的尘世财产,在海滩上某个炎热的地方买一个酒吧,然后试着用它谋生
  • 其他
有人能解释一下这些解决方案是否有效以及为什么有效吗?
(我的另一个问题是,我自己无法使用MATLAB进行测试,因为我无法访问安装MATLAB的机器。这就是为什么我还要问“建议的解决方案是否可行”)

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

我认为发生的事情是,您的库从它所链接的Boost库中导出所有符号(可以通过
readelf--dyn syms-W
进行验证)。在运行时,dynamic linker会注意到这一点,并将符号重新绑定到不同版本的Boost(因为它恰好更早加载,所以会覆盖库使用的符号)

您要做的是告诉gcc您不希望导出Boost符号,或者您不希望它们在运行时可插入。有几种解决方案,最好是编译并链接到
-fvisibility=hidden
(注意Boost也需要链接到这个标志)。这将阻止从库中导出任何函数,除非您使用
\uuuuu属性((可见性(“隐藏”))
(当然,您需要对库接口函数进行注释)

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

现在谈谈剩下的问题

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

你可以这样做,但如果第三方在某个时候升级他们的升级,这可能会中断

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


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

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

我认为发生的事情是,您的库从它所链接的Boost库中导出所有符号(可以通过
readelf--dyn syms-W
进行验证)。在运行时,dynamic linker会注意到这一点,并将符号重新绑定到不同版本的Boost(因为它恰好更早加载,所以会覆盖库使用的符号)

您要做的是告诉gcc您不希望导出Boost符号,或者您不希望它们在运行时可插入。有几种解决方案,最好是编译并链接到
-fvisibility=hidden
(注意Boost也需要链接到这个标志)。这将阻止从库中导出任何函数,除非您使用
\uuuuu属性((可见性(“隐藏”))
(当然,您需要对库接口函数进行注释)

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

现在谈谈剩下的问题

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

你可以这样做,但如果第三方在某个时候升级他们的升级,这可能会中断

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


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

“它们是静态链接的”-你100%确定你链接了Boost的静态版本吗?
readelf--dyn syms-W youlib.so的输出是否显示定义的Boost符号(而不是“UND”)?“并且它们是静态链接的”-您100%确定链接到Boost的静态版本吗?
readelf--dyn syms-W youlib.so的输出是否显示定义的Boost符号(而不是“UND”)?
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 ...