本章主要分析: 为什么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,向系统发送消息
继续执行代码,会走 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
网友评论