ios alloc 底层实现分析

319 阅读2分钟

首先上源码,苹果源码的地址 当然也可以直接参照cooci 老师的博客掘金地址,以及可以直接调试的objc的源码

  • 引入正题之前先介绍三种下符号断点的方式
  1. 先打一个断点,此时在断点处停下,然后按住control

    符号断点1.png 此时点击step in,就会进入汇编

    Screen Shot 2021-06-14 at 2.25.50 PM.png

  2. 通过add symbolic breakpoint 符号断点2.png 点击symbolic breakpoint,添加符号断点,再次debug

    符号断点3.png

  3. 打开汇编,always show disassembly

    符号断点4.png

  • 有了符号断点的知识,后面终于进入整体了,我们先不要直接看源码,可以直接先通过下符号断点的方式,看底层alloc 的流程. 关于这个流程,alloc的调用如下图

Screen Shot 2021-06-14 at 3.20.20 PM.png 但是对比源码,以为流程图画错了, image.png 在我们加载类的时候会看到里面有这么一个方法fixupMessageRef

image.png 此时进入这个方法看下 image.png 会看到这个方法里面做了一些关于SEL 和IMP 绑定的修正:alloc 的IMP指向的是_objc_alloc. 是不是此时一切就豁然开朗啦,原来SEL alloc实际的实现是_objc_alloc.

同时我们来查看下llvm 的源码

image.png

image.png

image.png 发现当mac os 10.10 之后都会将SEL alloc的IMP指向objc_alloc. apple 会在底层对alloc 方法进行拦截, alloc 会标记成objc_alloc

image.png 因此也解释了为什么call_alloc会调用两次的原因。第一次是因为apple 拦截了alloc方法并进行标记objc_alloc, 执行到objc_alloc之后,在调用objc_messageSend 发送了一个alloc的消息,由于第一次已经被标记了,所以第二次调用alloc, 会走alloc正常的流程。

image.png

image.png