三、NSObject的alloc源码分析

本章主要分析: 为什么NSObject *objc = [NSObject alloc] 为什么没有走上一章分析的alloc源码的流程

第一步:探索[NSObject alloc] 走的哪个方法

  • 将断点断在 NSObject *obj = [NSObject alloc];
 NSObject *obj = [NSObject alloc];
 LGPerson *p = [LGPerson alloc];
  • 打开 Debug -> Debug workflow -> 勾选 Always Show Disassemly 汇编调试


    NSObject alloc.png

发现 [NSObject alloc] 并没有走 alloc 方法,而是走 objc_alloc

第二步:搜索NSObject 为什么走 objc_alloc?
通过第一步中汇编调试发现:NSObject 和 LGPerson 都调用了 objc_alloc,那么就会有两个问题:

  • 为什么 NSObject 调用 alloc 方法 会走到 objc_alloc?
  • 为什么LGPerson 中的 alloc 会走两次,先调用 objc_alloc,再调用 alloc?
    通过加断点发现 LGPerson 第一次的 alloc 会走 objc_alloc->callAlloc 方法中最后一行代码:objc_msgSend,向系统发送消息
125.png

继续执行代码,会走 alloc -> _objc_rootAlloc -> callAlloc上一章分析的alloc源码的流程

126.png

所以:LGPerson 走了两次的原因是先执行 objc_alloc ,再通过查找sel,执行 alloc 方法。

那么问题 为什么会先走 objc_alloc?

通过 LLVM 源码(llvm-project) 来分析

  • 在源码中搜索 OMF_alloc


    OMF_alloc.png
  • 跳转到 EmitObjCAlloc 方法

/// Allocate the given objc object.
///   call i8* \@objc_alloc(i8* %value)
llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value,
                                            llvm::Type *resultType) {
  return emitObjCValueOperation(*this, value, resultType,
                                CGM.getObjCEntrypoints().objc_alloc,
                                "objc_alloc");
}

所以可以得出:NSObject 中的 alloc 会走 objc_alloc, 其实是由系统级别的消息处理逻辑,所以 NSObject 的 初始化是由系统完成,没有走 alloc 的源码流程。

总结:NSObject 的 alloc 和 自定义的 alloc 的流程

NSObject:

[NSObject alloc] -> objc_alloc -> callAlloc -> _objc_rootAllocWithZone

自定义类

[LGPerson alloc] -> objc_alloc -> callAlloc -> objc_msgSend -> alloc -> _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone -> _class_createInstanceFromZone

你可能感兴趣的:(三、NSObject的alloc源码分析)