iOS-底層原理 06:malloc 源碼分析 思路

iOS 底層原理 文章匯總

iOS-底層原理 02:alloc & init & new 源碼分析文章中,alloc有3個核心操作,其中一個就是calloc,即申請內存,這就是今天需要探索的內容,其實探索的本質也是為了驗證 ios中對象中實際的對齊方式是8字節對齊

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創建一個指針
  • 進入calloc的源碼實現,其中的關鍵代碼在于1713行的 malloc_zone_calloc
    • 其中default_zone是一個默認的zone,目的就是引導程序進入一個創建真正zone的流程
  • 進入malloc_zone_calloc的源碼實現,關鍵代碼是1441行的zone->calloc

    • 其中zone->calloc傳入的zone 就是 上一步中的 default_zone
    • 這個關鍵代碼的目的就是申請一個指針,并將指針地址返回
  • 在進入zone->alloc的源碼,發現是一個calloc的聲明,到此,源碼就無法繼續跟進了

那么重點來了!!!想要繼續跟進源碼,可以通過以下方式:

  • malloc_zone_calloc中的關鍵代碼,即ptr = zone->calloc(zone, num_items, size);處,加一個斷點,然后運行

  • 斷點斷在 ptr位置,想要進入zone->calloc源碼實現,有兩種方式:

    • 按住control + step into,進入calloc的源碼實現

    • ,然后通過lldb命令p zone->callocde查找源碼實現,通過打印得知zone->calloc的源碼實現在default_zone_calloc方法,然后全局搜索default_zone_calloc方法,找到具體實現

  • 進入calloc的源碼實現,其中主要由兩部分操作
    • 創建真正的zone,即runtime_default_zone方法
    • 使用真正的zone進行calloc

斷點斷在zone的位置,此時通過lldb命令p zone->alloc 是不行的,因為zone沒有賦值

zone 未賦值的驗證

  • 進入runtime_default_zone的源碼實現

  • 進入inline_malloc_default_zone的源碼實現,通過查看malloc_zones的值發現是NULL,可以得出,此時的zone還未賦值

繼續跟蹤源碼

  • 回到default_zone_calloc方法,繼續執行,斷在zone->calloc部分,此時同樣可以通過上述的兩種方法任選其一進入 calloc的源碼實現nano_calloc
  • 進入nano_calloc方法,其中的關鍵代碼是 878,此時的p是pointer表示指針 和前面的 ptr一樣,主要由兩部分邏輯
    • 如果要開辟的空間小于 NANO_MAX_SIZE,則進行則進行nanozone_tmalloc
    • 反之,就進行helper_zone流程
  • 進入_nano_malloc_check_clear源碼,將if else 折疊,看主流程
    • 其中segregated_next_block 就是指針內存開辟算法,目的是找到合適的內存并返回
    • slot_bytes是加密算法的(其目的是為了讓加密算法更加安全,本質就是一串自定義的數字)
  • 進入segregated_size_to_fit加密算法源碼, 通過算法邏輯,可以看出,其本質就會16字節對齊算法
#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的倍數,跟 k/16 * 16一樣
    //---16字節對齊算法,小于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:內存對齊原理文末,已經提及過該算法,這里不再過多說明

  • 回到_nano_malloc_check_clear方法,進入segregated_next_block源碼,這個方法主要就是獲取內存指針
    • 但是如果是第一次走到segregated_next_block函數,band不存在,緩存也不會存在,所以會調用segregated_band_grow,來開辟新的 band
  • 進入segregated_band_grow源碼,主要是開辟新的band

先記錄libmalloc源碼中malloc分析的思路,需要時間研究源碼,后續再補充完善!!!

參考鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。