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

在 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” 即可。
————————————————
版权声明:本文为CSDN博主「luansxx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/luansxx/article/details/17056433

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章