解决Linux多个动态库间的符号冲突问题

      c和c++开发人员或多或少都使用过Linux动态库,但是很多时候我们都不会去深入了解其中的一些细节和原理,直到自己的程序出现莫名其妙的问题后才会去着手解决,我也是在遇到一些动态库的问题后才去深入寻找解决办法。比如项目中加载了多个动态库,自己的动态库本来只想调用自己动态库中的函数,但是却调用到了其他动态库的同名函数上了,导致运行时的程序崩溃。还有项目中用到了多个版本的openssl,这些版本的openssl怎么共存的问题。

      符号冲突暴露的时机可能是编译期,也可能是运行时。编译期的符号冲突一般不会产生太大的影响,如果是自己的项目代码, 只要找到冲突的符号,重命名其中某个符号就能解决,但是如果是其他外部库的代码,这个就不好改别人的代码,但是也可以将冲突的外部库进行封装来解决。如果是运行时的的符号冲突,一般就是动态库导致的。

     在Linux下编译动态库的时候,所有的符号默认都是导出的,也就是动态库中的函数名,类名等,在外部都是可见的。我们在使用动态库没有出现问题之前,都不会去关注这些动态库中的符号是不是导出的。大多数时候,动态库中符号冲突也不会出现,因为出现不同动态库中相同的函数名或者类名的情况也是很少的。顺便提一下,windows下,dll动态库中的符号默认是不导出的,只有在需要导出的函数或者类名前加__declspec(dllexport)才会导出。

     那linux下有没有类似window下的显式导出功能呢,有的。下面是介绍一种常用的只导出指定符号的方法。

        1、加编译器选项fvisibility=hidden,加了这个选项后,默认的符号都不会导出

        2、在需要导出的函数或者类名前加__attribute__ ((visibility("default")))

只导出几个必须的符号,就大大降低了多个动态库间的符号冲突问题。然而,这还不能完全解决问题,很多动态库在制作的时候都是默认的把所有符号导出,你没法保证自己的动态库不错误地引用到其他动态库中的符号。解决的办法也有两种:

一种是在编译期解决,就是在编译动态库的时候加参数-Wl,-Bsymbolic 这个参数是传给链接器的,这个编译参数的作用是:优先使用本动态库中的符号,而不是全局符号。这样即使其他动态库导出的符号和自己动态库中的符号同名,冲突也不会发生,运行自己动态库程序的时候会使用自己本动态库中的函数和类。

一种是在加载动态库的时候解决,如果你没法重新编译动态库,可以在加载动态库的时候自己使用dlopen函数加载动态库,然后在增加RTLD_DEEPBIND这个标志,这个标志的解释是这样的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值