linux 下 动态链接库 so 之间的符号冲突

来源:互联网 发布:情报通怎么样 知乎 编辑:程序博客网 时间:2024/06/09 15:59
在 linux 下编写动态链接库程序,需要注意 dll 之间的符号冲突。

当我们链接库需要提供给很多方集成使用,需要面对复杂的集成环境,其中一个大问题就是与第三方集成环境的符号冲突。

这些冲突有些不是通过严格控制名字空间解决的,比如当我们使用了一些开源库,我们不清楚第三方集成环境有没有这些库,即使有是不是版本匹配,我们也不想对第三方集成环境提太多要求,这会增加集成成本。在这种情况下,我们会将这些开源库静态链接到我们的动态链接库中,仅提供一个 so 文件。但是这样做不足以避免符号冲突。

linux 下的动态链接机制允许多个 so 库定义相同的符号,不会在构建时出现符号重复定义错误。这种冲突在运行时也不会出现错误警告信息,运行时链接过程一般使用重复定义的符号中最早出现的版本,除非明确使用 dlsym 系统 API 获取。

因此,在运行时,到底会绑定到那个版本的符号上,是不确定的事。这种冲突是双向的,我们的链接库可能错误使用了第三方集成环境的符号版本,另一方面,第三方环境也可能错误绑定我们的链接库中的开源库的符号版本。

解决冲突的方法是将我们使用的开源库里面的符号隐藏起来。程序构建分为编译和链接两步,在这两步都有隐藏符号的方法。

在编译阶段,可以指定符号的可见属性 __attribute__ ((visibility("hidden"))),比如:

void func() __attribute__ ((visibility("hidden")));

但是我们不可能对所有符号一个个添加可见属性,所以 gcc 提供了 -fvisibility=hidden 编译 flag,可以设置所有符号都隐藏。此时,需要为应该导出的符号明确可见属性,比如:

void export_func() __attribute__ ((visibility("default")));
在链接阶段,可以通过 version script 文件将符号分为 local、global 两类。要导出的符号归于 global 类。如我们创建文件 mylib.ver,内容为:

{        global:                export_func;        local: *;};
在链接时指定 flag:“-Wl,--version-script=mylib.ver” 即可。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 拼多多处罚下架怎么办 永久无法解绑支付宝怎么办 淘宝下单购买人数太多怎么办 新浪微博被拉黑暂时无法评论怎么办 闲鱼交易成功后卖家反悔怎么办 闲鱼买家不申请介入怎么办 支付宝安装不上怎么办 无线摄像机离wifi太远怎么办 安卓系统死机了怎么办 安卓手机开不了机怎么办 手机关机键坏了怎么办 华为手机接听电话声音小怎么办 小米6x游戏闪退怎么办 安卓8.0不兼容怎么办 安卓8.0应用闪退怎么办 安卓8.0不兼容的怎么办 游戏全屏只有一个分辨率选项怎么办 安卓6.0吃运行内存怎么办 小米手机王者荣耀录像不支持怎么办 win764位系统不兼容怎么办 安卓版本太高不兼容怎么办 安卓3.2.0不兼容怎么办 手机卡和手机不兼容怎么办 vivo手机下载吃鸡不兼容怎么办 vivox3t不兼容支付宝怎么办 移动sim卡坏了怎么办 cpu和主板不兼容怎么办 主板与cpu不兼容怎么办 cpu跟主板不兼容怎么办 软件与电脑不兼容怎么办 win8系统无限重启怎么办 安装微信旧版本登录提示升级怎么办 手机软件与系统不兼容怎么办 下载旧版本微信闪退登陆不了怎么办 企业微信一直登录失败怎么办 360浏览器9.1经常卡死怎么办 手机版爱奇艺看电影屏幕变小怎么办 找不到旧版本米聊怎么办 苹果id被锁了怎么办 新浪微博支付宝解绑失败怎么办 阿里妈妈升级看不到引流人数怎么办