建議先看下 IOS底層(三): alloc相關(guān)1.初探 alloc, init, new源碼分析
先看個(gè)例子


NSObject , alloc方法里面 加斷點(diǎn), 運(yùn)行我們會(huì)發(fā)現(xiàn)竟然沒有走+ (id)alloc方法
那么NSObject在走的是哪個(gè)方法呢?
打開 Debug→Debug Workflow勾選 Always Show Disassemly進(jìn)行匯編調(diào)試
alloc方法這邊打個(gè)斷點(diǎn), 運(yùn)行一下


我們可以看到都走了一個(gè)objc_alloc 方法
全局搜索 objc_alloc,可看到有一個(gè)這個(gè)方法

在objc_alloc中加一個(gè)斷點(diǎn),先暫時(shí)關(guān)閉匯編, 重新運(yùn)行下可看到, 的確走到這里來了

那么為什么NSObject走的是objc_alloc(Class cls) 這個(gè)方法?
原因主要是: NSObject 系統(tǒng)級(jí)別幫我們走完
這里我們需要一份LLVM源碼(llvm-project, 是系統(tǒng)級(jí)別的源碼)來具體分析下, objc_alloc是什么時(shí)候有的, 而它又與alloc有什么區(qū)別。
LLVM下載地址
查找下
通過alloc字符串或者omf_alloc:搜索, 找到tryGenerateSpecializedMessageSend方法

這里可以看到, 如果當(dāng)前方法sel如果是alloc就會(huì)調(diào)用一個(gè)EmitObjCAlloc方法, 點(diǎn)進(jìn)去看一下

可以看到這里調(diào)用了一個(gè)objc_alloc。由此可以得出NSObject中的alloc會(huì)走到objc+alloc, 其實(shí)這部分是由系統(tǒng)級(jí)別的消息處理邏輯, 固NSObject的初始化是由系統(tǒng)完成, 因此不會(huì)走傳統(tǒng)的alloc的源碼中。
j接下來我們看下自定義類SATest
NSObject *objc = [NSObject alloc];
SATest *objc1 = [SATest alloc];
首先SATest 是繼承NSObject的, NSObject是其根類/基類/父類, 所有自定義的類都繼承于NSObject。
我們由LLVM已經(jīng)得出, NSObject都會(huì)走一個(gè)objc_alloc方法。那么繼承于NSObject也會(huì)走一個(gè)objc_alloc方法。這個(gè)也是之前我們那張匯編的圖片SATest, 也走了objc_alloc原因
那么問題也出現(xiàn)了
objc_alloc → callAlloc 并不應(yīng)該走
alloc→_objc_rootAlloc→_objc_rootAlloc→callAlloc
我們?cè)?code>callAlloc打個(gè)斷點(diǎn)發(fā)現(xiàn), 的確是走了2次, 這就很離譜?

我們?cè)?callAlloc跟一下流程

可看到自定義類中objc_alloc, callAlloc走的是(id, SEL))objc_msgSend)(cls, @selector(alloc));, 即向系統(tǒng)發(fā)送消息, 沒有走_objc_rootAllocWithZone
這里我們需要再看下LLVM中 GeneratePossiblySpecializedMessageSend消息發(fā)送這里

我們可以看到但凡是runtime的消息發(fā)送必然現(xiàn)在走if判斷, 由于傳入sel是@selector(alloc)并沒有走過, 沒有找到所以這里的if判斷是false, 走GenerateMessageSend這個(gè)方法, 即調(diào)用sel→alloc方法, 即alloc→_objc_rootAlloc→_objc_rootAlloc→callAlloc
總結(jié):
NSObject

自定義類
