简介

很久之前写过一篇[Xcode]记载一个链接过程的圈套,最近再解决oncall问题时,排查下来发现也是一个链接次序问题引起的疑难杂症。希望能给读者一些启示。

Protocol数量不对

某天我被拉入一个群中,oncall的同学告诉我CI打出的IPA反汇编后某个Protocol只要21个方法。正常状况应该是28个方法。我有些疑惑为什么要去反汇编IPA去看一个Protocol有几个方法呢?

正常状况运转时运用- (BOOL)respondsToSelector:(SEL)aSelector;后检测实例是否存在对应方法,存在的话直接发送音讯即可。有几个Protocol方法存在都无关紧要。

我主张结合linkmap去查询为什么respondsToSelector是找不到对应的方法。经过一系列排查发现是BDXContainer有着这样一段代码会依据Protocol中的方法数量来运转一些逻辑。其中protocol_copyMethodDescriptionList会依据传入的第一个Protocol类型参数,获取其中方法列表。在异常时这里的count一直返回21。直接导致后续respondsToSelector判别失利。

[LD]iOS二进制组件化与Protocol的潜在风险

排查过程

1.通过排查linkmap排查毫无发展。依据上面的信息。首要置疑是CI上的组件版别号比较老或者存在缓存等因素导致运用了旧的版别。

验证后组件版别正确,头文件内容正确。

2.上述排查方法失效后陷入了窘境,CI上的头条项目运用了jojo+bazel来进行构建,欠好获取到对应的编译参数。否则能够独自获取到方针文件(.o)对齐反编译一探究竟。直到别的一个项目西瓜本地也遇到了这个问题。同一个问题在CI Bazel与本地Xcode同时出现。

先是排查头文件处理错误的问题。运用Xcode预处理将头文件翻开。发现预处理一切正常。说明没有运用错误的头文件。

然后咱们置疑起了Dolphin(C/C++/OC/Swift分布式缓存)的问题。 咱们运用Dolphin构建出一个方针文件(.o)。封闭Dolphin再构建出一个方针文件(.o)。

通过对两个方针文件反汇编均能找到对应Protocol的28个函数。Dolphin问题基本排除。

以下是运用hooper反编译的成果。能够看到Protocol方法数量存在于一个结构体之中。

[LD]iOS二进制组件化与Protocol的潜在风险

3.承认编译问题后只能剩下链接问题。因为西瓜运用了zld,所以封闭zld和strip等再验证一次。

封闭zld后调试验证对应Protocol方法数量仍为21个。查询又陷入了窘境。此刻剩下的排查方法或许只剩下调试ld64了。

4.机缘巧合下,让Oncall同学搜索用到BDXContainerLifecycleProtocol地方。发现组件库都用到了这个Protocol。结合反编译的成果。可知每个用到该Protocol方针文件中(.o)中都存在一个symbol(_OBJC$_PROTOCOL_INSTANCE_METHODS_OPT_BDXContainerLifecycleProtocol)。再结合之前的经验[[Xcode]记载一个链接过程的圈套]。忽然想到这或许是个链接次序引起的问题。

按照链接次序的思路排查。很快就找到了BDUGLuckyDog中的BDUGLynxBaseVCBDUGLuckyDog这个库在二进制组件化时锁定了BDXServiceCenter的版别,打包出来的静态库中BDUGLynxBaseVC.o总是只要21个方法。起先 BDXServiceCenter也是21方法时运转起来或许没什么问题。跟着BDXServiceCenterProtocl中方法数量添加并且BDU前缀的库在链接时排名比较靠前。所以链接器面临多个BDXContainerLifecycleProtocol总是挑选了BDUGLynxBaseVC.o中的BDXContainerLifecycleProtocol(先到先得)。也就造成了此次的问题。

解决方案

既然找到了BDUGLuckyDog那么晋级其以来的BDXServiceCenter即可。

可是二进制组件中仍存在需求同名Protocl且方法数量各不相同。说不定某一天还会遇到类似问题。我考虑了许久。认为有以下几种方法能够从底子防止这类问题。

  • 二进制架构中制止运用protocol_copyMethodDescriptionList
  • 严格遵守语义化版别号标准,关于Protocol变更归于API Breaking Change添加大版别号,一切依赖的组件都要从头出包。
  • Pipeline添加检测手法办理重复代码问题。
  • 切换满意源码。

总结

公司内部静态库关于静态库和动态库的运用依然短少一些方法论。短少检测手法。一朝一夕便会影响研制功率。关于静态库、动态库开发标准于办理应当提上日程。

关于App-Infra DevOps 团队

App-Infra DevOps团队作为公司的移动研制中台,致力于优化公司各事务的研制和交给过程中的质量、成本、安全、功率和体验。到目前为止咱们已经有超过上百个事务接入,1万+人日常运用;平均每天支撑 3000+研制使命顺利交给;建设了业界抢先且或许是国内最大的构建集群,每天运转20万+次构建使命。

字节跳动当前作为国内甚至全球最大的”使用工厂”,咱们等待更多有热心和创造力的同学参加,为这座工厂打造业界最抢先,最高效的生产东西。

咱们的作业内容主要包括:

  • 供给使命办理,工程办理,开发调试,交给流程支持的一站式同开发渠道。同时供给Native版及Web版,方针成为下一代端云协同的研制根底设施。
  • 客户端 IDE 云化的探索性项目,目的是供给一整套线上编码、调试环境,让用户翻开浏览器就能够进行代码开发,满意不同场景的需求,提高研制功率。

参加咱们

北京-高档iOS开发工程师 — 终端技能 job.toutiao.com/s/2YHxkXW

职位描绘

1、担任头条公司产品的通用技能研制和性能优化,完结高质量编码和测验作业 2、结构维护,通用东西开发等 3、规划杰出的代码结构,不断迭代重构; 4、前沿技能研究,承当要点、难点的技能攻坚

职位要求

1、本科及以上学历,计算机、通讯等相关专业 2、具有扎实的编程功底,杰出的规划能力和编程习气 3、熟练掌握Objective-C,C++,了解Swift的优先 4、了解bash/python/ruby/js的优先

上海-高档iOS开发工程师 — 根底技能 job.toutiao.com/s/2YHm8a7

职位描绘

  1. 担任公司客户端产品的通用根底技能研制,完结高质量编码和测验作业
  2. 通用研制东西开发、通用结构开发等
  3. 规划杰出的代码结构,不断迭代重构
  4. 前沿技能研究,承当要点、难点的技能攻坚

职位要求

  1. 本科及以上学历,计算机、通讯等相关专业
  2. 具有扎实的编程功底,杰出的规划能力和编程习气
  3. 熟练掌握Objective-C,C++,了解Swift的优先
  4. 了解前后端相关和跨渠道技能、了解bash/python/ruby/js等语言和相关结构的优先

杭州-高档iOS开发工程师 — 根底技能 job.toutiao.com/s/2YHdPAE

职位描绘

  1. 担任公司跨渠道相关技能研制,完结高质量编码和测验作业
  2. 担任通用跨端结构及周边东西开发等
  3. 规划杰出的代码结构,不断迭代重构
  4. 前沿技能研究,承当要点、难点的技能攻坚

职位要求

  1. 本科及以上学历,计算机、通讯等相关专业
  2. 具有扎实的编程功底,杰出的规划能力和编程习气
  3. 熟练掌握Objective-C,C++,了解Swift的优先
  4. 了解前后端相关和跨渠道技能,了解bash/python/ruby/js等语言和相关结构的优先