在iOS-底層原理 02:alloc & init & new 源碼分析文章中,alloc有3個核心操作,其中一個就是calloc,即申請內(nèi)存,這就是今天需要探索的內(nèi)容,其實探索的本質(zhì)也是為了驗證 ios中對象中實際的對齊方式是8字節(jié)對齊
objc4中分析calloc 源碼
- 首先從alloc進入objc的源碼,找到
obj = (id)calloc(1, size);操作,涉及的方法順序是alloc --> _objc_rootAlloc --> callAlloc --> _objc_rootAllocWithZone --> _class_createInstanceFromZone
這里calloc的探索需要切換到 libmalloc源碼中,可以在這里下載最新版,接著往下走
libmalloc中分析calloc源碼
- 在可編譯的libmalloc中定義一個可編譯的target,在main中使用
calloc創(chuàng)建一個指針
- 進入calloc的源碼實現(xiàn),其中的關(guān)鍵代碼在于
1713行的 malloc_zone_calloc- 其中
default_zone是一個默認(rèn)的zone,目的就是引導(dǎo)程序進入一個創(chuàng)建真正zone的流程
- 其中
-
進入
malloc_zone_calloc的源碼實現(xiàn),關(guān)鍵代碼是1441行的zone->calloc
- 其中
zone->calloc傳入的zone 就是 上一步中的default_zone - 這個關(guān)鍵代碼的
目的就是申請一個指針,并將指針地址返回
- 其中
-
在進入
zone->alloc的源碼,發(fā)現(xiàn)是一個calloc的聲明,到此,源碼就無法繼續(xù)跟進了
那么重點來了?。。∠胍^續(xù)跟進源碼,可以通過以下方式:
在
malloc_zone_calloc中的關(guān)鍵代碼,即ptr = zone->calloc(zone, num_items, size);處,加一個斷點,然后運行-
斷點斷在 ptr位置,想要進入zone->calloc源碼實現(xiàn),有兩種方式:
按住
control+step into,進入calloc的源碼實現(xiàn)-
,然后通過lldb命令
p zone->callocde查找源碼實現(xiàn),通過打印得知zone->calloc的源碼實現(xiàn)在default_zone_calloc方法,然后全局搜索default_zone_calloc方法,找到具體實現(xiàn)
- 進入calloc的源碼實現(xiàn),其中主要由兩部分操作
- 創(chuàng)建真正的
zone,即runtime_default_zone方法 - 使用真正的
zone進行calloc
- 創(chuàng)建真正的
斷點斷在zone的位置,此時通過lldb命令p zone->alloc 是不行的,因為zone還沒有賦值
zone 未賦值的驗證
-
進入
runtime_default_zone的源碼實現(xiàn)
-
進入
inline_malloc_default_zone的源碼實現(xiàn),通過查看malloc_zones的值發(fā)現(xiàn)是NULL,可以得出,此時的zone還未賦值
繼續(xù)跟蹤源碼
- 回到
default_zone_calloc方法,繼續(xù)執(zhí)行,斷在zone->calloc部分,此時同樣可以通過上述的兩種方法任選其一進入 calloc的源碼實現(xiàn)nano_calloc
- 進入
nano_calloc方法,其中的關(guān)鍵代碼是 878,此時的p是pointer表示指針和前面的 ptr一樣,主要由兩部分邏輯- 如果要開辟的空間小于
NANO_MAX_SIZE,則進行則進行nanozone_t的malloc - 反之,就進行
helper_zone流程
- 如果要開辟的空間小于
- 進入
_nano_malloc_check_clear源碼,將if else 折疊,看主流程- 其中
segregated_next_block就是指針內(nèi)存開辟算法,目的是找到合適的內(nèi)存并返回 -
slot_bytes是加密算法的鹽(其目的是為了讓加密算法更加安全,本質(zhì)就是一串自定義的數(shù)字)
- 其中
- 進入
segregated_size_to_fit加密算法源碼, 通過算法邏輯,可以看出,其本質(zhì)就會16字節(jié)對齊算法
#define SHIFT_NANO_QUANTUM 4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) // 16
static MALLOC_INLINE size_t
segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey)
{
size_t k, slot_bytes;
//k + 15 >> 4 << 4 --- 右移 + 左移 -- 后4位抹零,類似于16的倍數(shù),跟 k/16 * 16一樣
//---16字節(jié)對齊算法,小于16就成0了
if (0 == size) {
size = NANO_REGIME_QUANTA_SIZE; // Historical behavior
}
k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta
slot_bytes = k << SHIFT_NANO_QUANTUM; // multiply by power of two quanta size
*pKey = k - 1; // Zero-based!
return slot_bytes;
}
在iOS-底層原理 05:內(nèi)存對齊原理文末,已經(jīng)提及過該算法,這里不再過多說明
- 回到
_nano_malloc_check_clear方法,進入segregated_next_block源碼,這個方法主要就是獲取內(nèi)存指針- 但是如果是第一次走到
segregated_next_block函數(shù),band不存在,緩存也不會存在,所以會調(diào)用segregated_band_grow,來開辟新的band
- 但是如果是第一次走到
- 進入
segregated_band_grow源碼,主要是開辟新的band
先記錄libmalloc源碼中malloc分析的思路,需要時間研究源碼,后續(xù)再補充完善!!!













