最近遇到的一个比较有趣的问题,linux系统下动态库符号冲突造成了运行异常,简单来说就是主程序在某些高版本的系统上间接依赖到了系统的动态库libxxx.so(瞎起的名字),而这个动态库导出的符号与项目中的动态库A符号冲突,导致在实际运行时出现异常,在查看堆栈后发现程序最终执行的是libxxx.so中的函数而不是A中的。在网上搜了很多篇相关的博文,终于找到了解决方案:
在动态库A的cmakelists.txt中设置链接器属性-Bsymbolic
set_target_properties(my_executable PROPERTIES LINK_FLAGS "-Wl,-Bsymbolic")
这样就可以保证即使其他动态库导出的符号和自己动态库中的符号同名,冲突也不会发生,
运行自己动态库程序的时候会使用自己本动态库中的函数和类。
正常情况下,在 linux 平台上 (不使用 - Bsymbolic),加载的目标文件中第一次出现的符号将在程序中一直被使用,不论是定义在静态可执行部分,还是在动态目标文件中。这是通过符号抢占 (symbol preemption) 来实现的。动态加载器构建符号表,所有的动态符号根据该符号表被决议。所以正常情况下,如果一个符号实例出现在动态库(DSO)中,但是已经在静态可执行文件或者之前加载的动态库中被定义,那么以前的定义也将被用于当前的动态库中。
-Bsymbolic
遵循 ELF DF_SYMBOLIC 语义:所有定义的符号都是不可抢占的,优先使用本地符号。