美文网首页
iOS底层原理03:NSObject的alloc 源码分析

iOS底层原理03:NSObject的alloc 源码分析

作者: 黑白森林无间道 | 来源:发表于2021-03-20 22:07 被阅读0次

    本文主要探索NSObject中的alloc是与自定义类的alloc源码流程的区别,以及为什么NSObject中的alloc不走源码工程。

    NSObject的alloc无法进入源码的问题

    • 首先在objc4-818可编译源码中的main函数中增加一个NSObject定义的对象,NSObjectHTPerson同时加上断点
    image
    • alloc的源码实现中加一个断点,同时需要暂时关闭断点
    image
    • 运行target,断点断在NSObject部分,打开alloc源码的断点,然后继续执行,会出现以下这种现象
    image

    探索过程

    【第一步】探索[NSObject alloc]走的是哪步源码

    接下来,我们就来探索为什么NSObject的alloc会出现这种情况,首先,

    • 打开Debug --> Debug Workflow --> 勾选 Always Show Disassemly,开启汇编调试
    • 关闭源码的断点,只留main中的断点,重新运行程序,然后通过下图的汇编可以发现NSObject并没有走 alloc源码,而是走的objc_alloc
    image
    • 然后关闭汇编调试,在全局搜索 objc_alloc,在objc_alloc中加一个断点,先暂时关闭
    • 重新运行进行调试,断住,然后打开objc_alloc的断点,发现会进入objc_alloc的源码实现,此时查看 clsNSObject
    image

    【第二步】探索 NSObject 为什么走 objc_alloc?

    首先,我们来看看 NSObjectHTPerson的区别

    • NSObjectiOS中的基类,所有自定义的类都需要继承自NSObject
    • HTPerson 是继承自NSObject类的,重写了NSObject中的alloc方法

    然后根据第一步中汇编的显示,可以看出,NSObjectHTPerson 都调用了objc_alloc,所以这里就有两个疑问

    • 为什么NSObject 调用alloc方法 会走到 objc_alloc 源码?
    • 为什么HTPerson中的callAlloc 会走两次?即调用了alloc,进入源码,然后还要走到 objc_alloc

    HTPerson中callAlloc走两次的原因

    • 首先,需要在源码中调试,在mainHTPerson加断点,断在HTPerson,再在allocobjc_alloccallAlloc 源码加断点,运行demo,会断在objc_alloc源码中(重新运行前需要暂时关闭源码中的所有断点)
    image
    • 继续运行,发现HTPersonalloc会走到 objc_alloc --> callAlloc方法中最下方的objc_msgSend,表示向系统发送消息
    image

    以下是第二次走到callAlloc方法中的调用堆栈情况

    image

    所以由上述调试过程可以得出,HTPerson两次callAlloc的原因是首先需要去查找sel,以及对应的imp的关系,当前需要查找的是 alloc 的方法编号,但是为什么会找到objc_alloc?这个就需要问系统了,肯定是系统在底层做了一些操作。请接着往下看

    NSObject中alloc走到objc_alloc的原因

    这部分需要通过 LLVM源码(即llvm-project)来分析
    准备工作:首先需要一份llvm源码

    • 在llvm源码中搜索objc_alloc
    image
    • 搜索shouldUseRuntimeFunctionForCombinedAllocInit,表示版本控制
    image
    • 搜索tryEmitSpecializedAllocInit,非常著名的特殊消息发送,在这里也没有找到 objc_alloc
    image
    • 继续尝试,开启上帝视角,通过alloc字符串搜索,如果还找不到,还可以通过omf_alloc:找到tryGenerateSpecializedMessageSend,表示尝试生成特殊消息发送
    image
    • 然后在这个case中可以找到调用alloc,转而调用了objc_objc的逻辑,其中的关键代码是EmitObjCAlloc
    image
    • 跳转至EmitObjCAlloc的定义可以看到alloc 的处理是调用了 objc_alloc
    image

    由此可以得出 NSObject中的alloc 会走到 objc_alloc,其实这部分是由系统级别的消息处理逻辑,所以NSObject的初始化是由系统完成的,因此也不会走到alloc的源码工程中

    相关文章

      网友评论

          本文标题:iOS底层原理03:NSObject的alloc 源码分析

          本文链接:https://www.haomeiwen.com/subject/qjdgcltx.html