本章主要分析: 為什么NSObject *objc = [NSObject alloc] 為什么沒有走上一章分析的alloc源碼的流程
第一步:探索[NSObject alloc] 走的哪個(gè)方法
- 將斷點(diǎn)斷在 NSObject *obj = [NSObject alloc];
NSObject *obj = [NSObject alloc];
LGPerson *p = [LGPerson alloc];
-
打開 Debug -> Debug workflow -> 勾選 Always Show Disassemly 匯編調(diào)試
NSObject alloc.png
發(fā)現(xiàn) [NSObject alloc] 并沒有走 alloc 方法,而是走 objc_alloc
第二步:搜索NSObject 為什么走 objc_alloc?
通過第一步中匯編調(diào)試發(fā)現(xiàn):NSObject 和 LGPerson 都調(diào)用了 objc_alloc,那么就會(huì)有兩個(gè)問題:
- 為什么 NSObject 調(diào)用 alloc 方法 會(huì)走到 objc_alloc?
- 為什么LGPerson 中的 alloc 會(huì)走兩次,先調(diào)用 objc_alloc,再調(diào)用 alloc?
通過加斷點(diǎn)發(fā)現(xiàn) LGPerson 第一次的 alloc 會(huì)走 objc_alloc->callAlloc 方法中最后一行代碼:objc_msgSend,向系統(tǒng)發(fā)送消息

繼續(xù)執(zhí)行代碼,會(huì)走 alloc -> _objc_rootAlloc -> callAlloc上一章分析的alloc源碼的流程

所以:LGPerson 走了兩次的原因是先執(zhí)行 objc_alloc ,再通過查找sel,執(zhí)行 alloc 方法。
那么問題 為什么會(huì)先走 objc_alloc?
通過 LLVM 源碼(llvm-project) 來分析
-
在源碼中搜索 OMF_alloc
OMF_alloc.png 跳轉(zhuǎn)到 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 會(huì)走 objc_alloc, 其實(shí)是由系統(tǒng)級(jí)別的消息處理邏輯,所以 NSObject 的 初始化是由系統(tǒng)完成,沒有走 alloc 的源碼流程。
總結(jié):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

