纵有疾风起
人生不言弃

关于duplicate symbol的思考

关于duplicate symbol的思考

iOS 开发中经常会遇到duplicate symbol这个问题,在编译链接的时候就会出现。相信有经验的开发都知道是怎么回事。那今天要讲的就是编译器在link时的一个坑!

讲个故事

最近在我们在发布SDK的时候,测试和预发,以及灰度都做完了。在正式发布的时候直接闪退了。看到这个问题直接一脸懵逼!

在SDK中,我们接入了人脸识别的SDK,在APP里面接入的时候,出现了闪退。挂在了RSA验签上,为什么同样的SDK会在正式发布的时候必闪退呢?由于涉及些公司安全东西,本篇是个阉割版,就不说解决过程了,我直接告诉结果了!

iOS系统API中并没有提供RSA公钥验签的算法API。既然挂在了这里,怀疑是扣了openssl的部分代码,进行了修改。APP里面也接入了openssl,然后在编译链接的时候,实际的RSA调用函数是外面的openssl的RSA,导致了crash。

探索

既然是两个库里面同时存在同样的symbol,为什么不报duplicate symbol的错误?我们下面写个demo进行测试下。

一、建立两个测试Library(LinkLibraryA和LinkLibraryB)和一个demo工程。

  • LinkLibraryA
//.h#ifndef LinkLibraryA_h#define LinkLibraryA_h#include <stdio.h>void sameMethod();#endif /* LinkLibraryA_h *///.cvoid sameMethod(){    printf("==== Library A ====");}
  • LinkLibraryB
//.h#ifndef LinkLibraryB_h#define LinkLibraryB_h#include <stdio.h>void sameMethod();#endif /* LinkLibraryB_h *///.cvoid sameMethod(){    printf("==== Library B ====");}
  • demo
//mian.c#include <stdio.h>#include "LinkLibraryA.h"int main(int argc, const char * argv[]) {        sameMethod();    return 0;}

二、测试过程

直接编译发现xcode并没有报duplicate symbol错误。

测试1——先链接LinkLibraryA再链接LinkLibraryB

关于duplicate symbol的思考插图

运行结果:==== Library A ====

测试2——先链接LinkLibraryB再链接LinkLibraryA

关于duplicate symbol的思考插图1

运行结果:==== Library B ====

通过以上两个测试,我们可以发现,存在同样的symbol,link的时候是不报错的!而且执行结果是依赖于静态库ld的顺序的!

进一步测试

  • 修改下LinkLibraryB
//.h#ifndef LinkLibraryB_h#define LinkLibraryB_h#include <stdio.h>int sameMethod();void testMethod(int a);#endif /* LinkLibraryB_h *///.cint sameMethod(){    printf("==== Library B ====");    return 1;}void testMethod(int a){    printf("==== test link===");}

sameMethod增加一个返回值,增加另个一入参是int的testMethod的函数。

  • 修改下demo测试代码
//main.c#include <stdio.h>#include "LinkLibraryB.h"int main(int argc, const char * argv[]) {        testMethod(sameMethod());        return 0;}

在main函数里面,我们在testMethod方法中,将sameMethod当入参传入。

测试1——先链接LinkLibraryA再链接LinkLibraryB

关于duplicate symbol的思考插图

运行结果:编译不通过!报duplicate symbol _sameMethod

测试2——先链接LinkLibraryB再链接LinkLibraryA

关于duplicate symbol的思考插图1

运行结果:=== Library B ======== test link===

总结

通过以上测试可以发现,如果linker解决unresolved symbols时,如果已经找到symbol,那么将不再去其他静态库里面寻找。

后面两组测试,第一组报错了,是因为ld LinkLibraryA的时候已经发现sameMethod,但是需要解决testMethod的symbol,接着ld LinkLibraryB的时候,LinkLibraryB里面的LinkLibraryB.o中找到了testMethod,但是,又一次发现了sameMethod,所以报错了!(后来,我把testMethod换成单独的文件去写,无论先链接谁,都是编译不报错的,但是逻辑和上面说的一样,从侧面也说明了linker优先寻找本静态库的符号,如果找到将不再去其他静态库进行寻找)

如果在other linker flags里面添加-all_load那么也就正常报错了,也就是我们所说的linker不允许存在重复的符号!

思考

通过以上测试,我们发现了在接入静态库的时候,容易出现此类问题。所以,我觉得以下几个点,大家还是需要关注下:

  • C没有函数重载,哪怕你参数多一个,编译链接的时候,也不会报错。因此,命名应有一套规范,防止和外面的C函数进行冲突

这点我觉得可以参考OC的方法,加上前缀。

  • C函数不对外开放的函数,尽量加上static,限制它的作用域
  • 对于接入的多个SDK依赖共同的SDK,请一定要仔细确认版本。

以上问题,大家注意下,希望大家别再踩了这个坑!

文章转载于:https://www.jianshu.com/p/782e1786c67a

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » 关于duplicate symbol的思考
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录