在上篇文章我們探究了自定義類
的alloc
源碼绎狭,接下來我們探究下NSObject
的alloc
源碼治专,我們會(huì)發(fā)現(xiàn)她并不會(huì)走alloc
的源碼工程 Why ?裂问?侧啼?這就是我們要探究的
我們在可編譯源碼中的main函數(shù)中創(chuàng)建一個(gè)NSObject
的對象和一個(gè)自定義
的對象,同時(shí)添加斷點(diǎn)堪簿,如下所示:
運(yùn)行工程痊乾,當(dāng)斷點(diǎn)斷在NSObject *obj = [NSObject alloc]
在alloc
源碼處添加斷點(diǎn),繼續(xù)運(yùn)行
我們會(huì)發(fā)現(xiàn)斷點(diǎn)并沒有斷在alloc
的源碼處戴甩,而是直接斷到了LCPerson *p1 = [LCPerson alloc]
這里符喝,也就是說[NSObject alloc]
并沒有走alloc
的源碼
接下來我們開啟匯編調(diào)試:Debug --> Debug Workflow --> 勾選 Always Show Disassemly
,只保留mian
函數(shù)中的斷點(diǎn)甜孤,其他均關(guān)閉或刪除协饲,運(yùn)行工程畏腕,通過匯編可以發(fā)現(xiàn)NSObject
并沒有走 alloc
源碼,而是走的objc_alloc
然后關(guān)閉匯編調(diào)試茉稠,在全局搜索 objc_alloc
描馅,在objc_alloc
中加一個(gè)斷點(diǎn),先暫時(shí)關(guān)閉
運(yùn)行程序而线,斷點(diǎn)斷在NSObject *obj = [NSObject alloc]
打開objc_alloc
處的斷點(diǎn)铭污,繼續(xù)執(zhí)行,發(fā)現(xiàn)會(huì)進(jìn)入objc_alloc
的源碼膀篮,此時(shí)查看 cls
是 NSObject
NSObject 為什么走 objc_alloc 嘹狞?
首先,我們來看看 NSObject 與 LCPerson的區(qū)別
NSObject
是iOS中的基類
誓竿,所有自定義的類都需要繼承自NSObjectLCPerson
是繼承
自NSObject
類的磅网,重寫
了NSObject
中的alloc
方法
然后根據(jù)之前匯編的顯示,可以看出筷屡,NSObject
和LCPerson
都調(diào)用了objc_alloc
涧偷,就有以下兩個(gè)疑問
:為什么
NSObject
調(diào)用alloc
方法 會(huì)走到objc_alloc
源碼?為什么
LCPerson
中的alloc
會(huì)走兩次
毙死?即調(diào)用了alloc
燎潮,進(jìn)入源碼,然后還要走到objc_alloc
扼倘?
LCPerson中alloc 走兩次 的 Why确封?
我們在源碼中調(diào)試,在main
中LCPerson
加斷點(diǎn)運(yùn)行程序再菊,再在alloc
隅肥、 objc_alloc
和 callAlloc
源碼加斷點(diǎn),繼續(xù)運(yùn)行袄简,發(fā)現(xiàn)LCPerson 第一次的alloc
會(huì)走到 objc_alloc --> callAlloc
方法中最下方的objc_msgSend
腥放,表示向系統(tǒng)發(fā)送消息
繼續(xù)執(zhí)行,會(huì)走到 alloc --> callAlloc --> _objc_rootAllocWithZOne
绿语,也就是iOS底層探究-03:alloc & init & new 源碼分析中的alloc流程
由上述調(diào)試過程可以得出秃症,LCPerson
走兩次
的原因是首先需要去查找sel
,以及對應(yīng)的imp
的關(guān)系吕粹,當(dāng)前需要查找的是 alloc
的方法編號种柑,但是為什么會(huì)找到objc_alloc
?這個(gè)就需要問系統(tǒng)了匹耕,肯定是系統(tǒng)在底層做了一些操作聚请,請繼續(xù)往下看
NSObject 中 alloc 走到 objc_alloc 的 why ?
這部分需要通過 LLVM源碼
(即 llvm-project
) 來分析
- 在llvm源碼中搜索
objc_alloc
,未找到
- 搜索
tryEmitSpecializedAllocInit
驶赏,非常著名的特殊消息發(fā)送炸卑,在這里也沒有找到objc_alloc
- 開啟上帝視角,通過
alloc
字符串搜索煤傍,如果還找不到盖文,還可以通過omf_alloc:
找到tryGenerateSpecializedMessageSend
,表示嘗試生成特殊消息發(fā)送
在這里可以找到調(diào)用alloc
蚯姆,轉(zhuǎn)而調(diào)用了EmitObjCAlloc
處理了objc_objc
的邏輯五续,代碼如下:
由此可以得出 NSObject
中的alloc
會(huì)走到 objc_alloc
,其實(shí)這部分是由系統(tǒng)級別的消息處理邏輯
龄恋,所以NSObject的初始化是由系統(tǒng)完成的疙驾,因此也不會(huì)走到alloc的源碼工程中