OC底层原理03 - NSObject的alloc 源码分析

本章主要是探索[NSObject alloc][自定义类 alloc]的源码流程是否一致,如果不一致具体是在哪里发生不同?

分析NSObject的alloc流程

发现问题

  1. 在main函数是增加一个NSObject对象的定义,并在对象处加上断点。


    image.png

    当程序运行起来时,停在断点处,即将开始执行[NSObject alloc]。

  2. 根据自定义类的alloc流程分析,知道第一步应该是进入alloc方法,即在alloc方法处加上断点。
    image.png
  3. 执行target,此时发现并未在断点处停下。这是为什么呢?

跟踪NSObject alloc的流程

  1. 运行target在即将开始执行[NSObject alloc]断点停下。

  2. 按住control+step into,通过汇编跟踪流程,此时汇编显示如下:


    image.png
  3. 由图可见,此时是进入了objc_alloc方法,下“objc_alloc”的符号断点,继续运行target,发现确实是进入了objc_alloc的源码中。

    image.png

  4. 继续进入callAlloc源码中

    image.png

  5. 由于NSObject没有自定义的allocWithZone方法,cls->ISA()->hasCustomAWZ()为0,因此会进入_objc_rootAllocWithZone方法。
    _objc_rootAllocWithZone方法中,跟自定义对象的alloc流程一致,完成alloc的重要三步骤:
    1. 计算需要开辟的内存空间大小(size = cls->instanceSize(extraBytes);
    2. 开辟指定大小的空间(obj = (id)calloc(1, size));
    3. 将对象与isa指针关联起来(obj->initInstanceIsa(cls, hasCxxDtor));

至此,NSObject的alloc就完成了。从流程分析中得到,NSObject的alloc确实不会进入到alloc方法中。

NSObject alloc 的调用流程图

image.png

NSObject alloc与自定义类的alloc区别

上面分析NSObject alloc首先进入的是objc_alloc方法,那自定义类的alloc会不会进入这个方法呢?

  1. 在main函数时增加一个自定义类对象的定义,并在定义处增加断点,运行target使其在断点处停下。


    image.png
  2. 打开objc_alloc的符号断点、alloc的符号断点。运行target发现断在了objc_alloc处。
    image.png
  3. 进入callAlloc,继续往下调试。
    image.png

    此时cls->ISA()->hasCustomAWZ()为1,即LGPerson有自定义在alloc方法。于是进入到objc_msgSend
  4. 通过objc_msgSend方法发送alloc的方法编号给当前类。此时进入了alloc方法中。
    image.png
  5. 再继续运行依次是_objc_rootAlloc方法,callAlloc方法,此时在callAlloc方法中cls->ISA()->hasCustomAWZ())为0,会进入_objc_rootAllocWithZone方法。
  6. _objc_rootAllocWithZone方法中完成alloc的重要三步骤。

自定义类的alloc调用流程

image.png

区别

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

总结

[NSObject alloc]流程与[LGPerson alloc]流程在cls->ISA()->hasCustomAWZ())判断前一致,但是由于LGPerson类重写了NSObject中的alloc方法,cls->ISA()->hasCustomAWZ())这个判断的结果与NSObject结果不一样。NSObject类直接去完成alloc重要三步骤,而LGPerson类需要通过sel找到alloc方法的编号后再执行alloc方法。

你可能感兴趣的:(OC底层原理03 - NSObject的alloc 源码分析)