在OC底層原理三:探索alloc (你好晕城,alloc大佬 )中我們介紹了alloc的三大核心函數(shù):
上一節(jié)我們已了解
instanceSize
的計算方式。 這一節(jié),我們深入探究calloc如何開辟空間
回顧一下我們之前的路徑,打開objc4
源碼,進入alloc
--> _objc_rootAlloc
--> callAlloc
--> _objc_rootAllocWithZone
--> _class_createInstanceFromZone
蚤假。
我們發(fā)現(xiàn)點擊calloc
進入內(nèi)部,只能看到calloc聲明吧兔。無法再繼續(xù)前進了
怎么辦磷仰? 繼續(xù)找源碼!
我們觀察到頂部路徑欄境蔼,可以看到calloc
的聲明是在malloc
源碼中灶平。
我們下載libmalloc
源碼下載最新版,接著往下走箍土。
libmalloc 源碼分析
打開libmalloc
項目民逼,新建一個HTTest
Target
切換至HTTest
Target,在main.m
中加入測試代碼。我們傳入指定size
大小為24,去模擬開辟空間
#import <Foundation/Foundation.h>
#import <malloc/malloc.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
void *p = calloc(1, 24);
NSLog(@"%p", p);
}
return 0;
}
點擊進入calloc
:
上述的default_zone
是一個默認(rèn)的空間大小涮帘。 size
是我們傳入的空間的大小拼苍,點擊進入malloc_zone_calloc
:
【 源碼分析能力】 觀察到返回值是
ptr
,所以最重要的應(yīng)該是ptr的賦值
其中
zone->calloc
的zone
是上一步中的default_zone
關(guān)鍵代碼的目的是申請
開辟內(nèi)存空間
并返回
一個指針地址
點擊進入
calloc
调缨,一個個進去看疮鲫。發(fā)現(xiàn)有聲明、有聯(lián)合體弦叶,但是沒有下一步的路徑了俊犯。
那么重點來了!I瞬浮燕侠!想要繼續(xù)跟進源碼,可以通過以下方式:
- 在
malloc_zone_calloc
中的關(guān)鍵代碼處加斷點立莉。
- 當(dāng)
程序運行
至斷點處時绢彤,兩種方法:
- 按住
control
+step into
,進入calloc
的源碼
-
控制臺
可以手動調(diào)用lldb
命令p zone->calloc
蜓耻。
-
發(fā)現(xiàn)
zone->calloc
的源碼實現(xiàn)在default_zone_calloc
方法
image.png -
全局搜索
default_zone_calloc
方法茫舶,找到具體實現(xiàn)
image.png 這里有2步重要的操作,
創(chuàng)建Zone
和使用真正的Zone調(diào)用alloc
,在創(chuàng)建之前刹淌,Zone
都為Null
進入runtime_default_zone
進入inline_malloc_default_zone
- 查看
malloc_zones
發(fā)現(xiàn)為NULL
,證明此時zone
確實未賦值饶氏。
在完成Zone
創(chuàng)建后讥耗,我們回到default_zone_calloc
方法
打印p zone->calloc
。
繼續(xù)搜索nano_calloc
疹启,核心代碼在886行
- 此時
p
是pointer指針古程,如果開辟的空間小于NANO_MAX_SIZE
,就走_nano_malloc_check_clear
,否則喊崖,調(diào)用nanozone->helper_zone
image.png
我們一般看到
help
,一般都不是主流程
進入_nano_malloc_check_clear
挣磨,將error
的異常判斷分支折疊起來,查看主流程
-
slot_bytes
是算法的鹽(本質(zhì)是一串字符串,提升算法的加密安全性) -
segregated_next_block
就是指針開辟算法
贷祈,目的是找到合適的內(nèi)存并返回。
進入segregated_size_to_fit
- 如果為0喝峦,初始值就設(shè)置為16
- 否則势誊, size加15,右移4位谣蠢,再左移4位粟耻。 這就是著名的
align16對齊
算法。 - 與OC底層原理三:探索alloc (你好眉踱,alloc大佬 )里的
align16
是一個意思
例如:
- size = 10時挤忙,二進制為
0000 0000 0000 1010
- 15的二進制為:
0000 0000 0000 1111
- size+15 = 25:
0000 0000 0001 1001
- 右移4位:
0000 0000 0000 0001
- 左移4位:
0000 0000 0001 0000
轉(zhuǎn)為10進制就是16。
其實就是16進制的進一法谈喳。
- 繼續(xù)進入
segregated_next_block
册烈,這里確定是否有足夠空間開辟,并返回開辟好的首地址指針
婿禽,即內(nèi)存指針
赏僧。 - 第一次走
segregated_next_block
方法,band
不存在扭倾,緩存也不存在淀零,所以會調(diào)用segregated_band_grow
,開辟新的band
膛壹。
image.png
好復(fù)雜驾中,也很重要。先mark模聋。 未完待續(xù)~~
參考鏈接: iOS 高級之美(六)—— malloc分析
下一節(jié)肩民,OC底層原理八:剖析isa (卸妝后的對象)