zoukankan      html  css  js  c++  java
  • C++库符号冲突杂谈

    符号冲突

    什么是符号冲突,就是库与库之间有相同的符号,使用者不知道用哪个;例如:A SDK有个符号a,B SDK也有个符号a,最终app调用a时,可能用的是A SDK的a,也可能是B SDK的a;这样的话,就会产生歧义,假如app想调用A SDK的a,但可能实际调用的却是B SDK的a,这样就会造成app行为异常,或是崩溃。

    静态库之间符号冲突

    静态库冲突经常会遇到下面几个问题:

    1. 为什么有些重复符号在链接时会报错,有些不会。
      首先静态库包含的是.o文件;.o文件就是对应的每个cpp/c文件编译后的产物。当链接时,链接器会按app使用到的函数逐个扫描静态库里的.o,如果发现要链接的.o里存在着已链接过的符号就会报错。不同编译器的链接算法不同,结果也不同。下面以vs 2015,xcode clang,ndk21来分析。
    • xcode clang: app使用到的函数是按字符串排列的,链接器会按这个顺序逐个扫描静态库,看下静态库里的.o是否存在在app使用到的函数,如果有就将.o所有符号放进全局符号表里,如果发现全局符号表里有相同的符号就报错
    def symsGlobal
    def symsAppCall
    for (sym in symsAppCall) {
        if (symsGlobal dont found sym) {
            for (symsObj in symsObjs) {
                if(symsObj found sym) {
                    if(symsGlobal dont contain symsObj) {
                        symsGlobal.addAll(symsObj)
                    }else {
                        print sym conflict
                        abort
                    }
                }
            }
        }
    }
    
    • vs2015 vc,ndk21 clang:链接器会按静态库链接顺序扫描静态库,看.o是否存在着app使用的函数,如果有就将.o所有符号放进全局符号表里,如果发现全局符号表里有相同的符号就报错
    def symsGlobal
    def symsAppCall
    for (symsObj in symsObjs) {
        for (sym in symsAppCall) {
            if (symsGlobal dont found sym) {
                if(symsObj found sym) {
                    if(symsGlobal dont contain symsObj) {
                        symsGlobal.addAll(symsObj)
                    }else {
                        print sym conflict
                        abort
                    }
                }
            }
        }
    }
    

    备注:上面的算法并不一定完全准确,因为这些链接器的代码并不开源,只是通过例子推测出来,有问题欢迎指正

    1. 下面,我们结合例子分析下
      情形 1 :
       
      WX20200827-111004@2x.png

      上面情况,无论在xcode或是vs2015/ndk,app先链接谁就用谁的d函数,而且不会链接报错。
      情形 2
       
      WX20200827-112737@2x.png

      上面的情况:
    • 在xcode下,因为链接器会先链接a函数,他会遍历当前的静态库,发现在a.o里,然后将a.o里的所有符号都放进全局符号里;当链接d函数时,因为d已经在全局符号,因此不需要将b.o放进全局符号,所以无论链接顺序是怎样,app始终用的是liba.a的d;
    • 在vs2015/ndk下,当liba.a先链接时,链接器会发现a.o里存在着app需要的a,d函数,因此将a.o里的所有符号放进全局符号,因为app需要的函数都链接完了,所以不需要将b.o放进全局符号。当libb.a先链接时,链接器会发现b.o存在着app需要的d函数,因此将b.o所有符号放进全局符号。当链接到liba.a时,发现a.o里存在着app需要的a函数,当将a.o所有符号放进全局符号里时,发现已存在了d函数,因此就报符号冲突错误。
      情形 3
       
      WX20200827-180339@2x.png

      上面情况:无论在xcode或是vs2015/ndk都会报链接出错,因为无论怎么链接,都需要将a.o和b.o里的符号放进全局符号里。
    1. 链接顺序可以确保app使用的是哪个库的符号吗。
      不同编译器结果不同;对于xcode不能保证,对于vs,ndk,只要不报错,app会用先链接的库的符号。


    作者:howardpangx
    链接:https://www.jianshu.com/p/fb5a5550f858
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    ------------------越是喧嚣的世界,越需要宁静的思考------------------ 合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。 积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。
  • 相关阅读:
    vue-打包为webapp,如何解决应用内跳转外部链接返回导致退出应用
    vue-引入mui.js报错如何处理
    微信小程序中-折线图
    Docker基础命令
    retry示例
    authenticate验证的流程
    django生产环境启动问题
    redis基本操作
    DBUtils数据库连接池
    外部程序调用Django模块的解决办法
  • 原文地址:https://www.cnblogs.com/feng9exe/p/14852562.html
Copyright © 2011-2022 走看看