天天看點

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

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

這裡calloc的探索需要切換到

libmalloc

源碼中,可以在這裡下載下傳最新版,接着往下走

libmalloc中分析calloc源碼

  • 在可編譯的libmalloc中定義一個可編譯的target,在main中使用

    calloc

    建立一個指針
    iOS-底層原理 06:malloc 源碼分析 思路
  • 進入calloc的源碼實作,其中的關鍵代碼在于

    1713行的 malloc_zone_calloc

    • 其中

      default_zone

      是一個預設的zone,目的就是引導程式進入一個建立真正

      zone

      的流程
      iOS-底層原理 06:malloc 源碼分析 思路
  • 進入

    malloc_zone_calloc

    的源碼實作,關鍵代碼是1441行的

    zone->calloc

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

      zone->calloc

      傳入的zone 就是 上一步中的

      default_zone

    • 這個關鍵代碼的

      目的

      就是

      申請一個指針,并将指針位址傳回

  • 在進入

    zone->alloc

    的源碼,發現是一個

    calloc

    的聲明,到此,源碼就無法繼續跟進了
    iOS-底層原理 06:malloc 源碼分析 思路

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

  • 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

      方法,找到具體實作
      iOS-底層原理 06:malloc 源碼分析 思路
  • 進入calloc的源碼實作,其中主要由兩部分操作
    • 建立真正的

      zone

      ,即

      runtime_default_zone

      方法
    • 使用真正的

      zone

      進行

      calloc

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

斷點斷在zone的位置,此時通過lldb指令

p zone->alloc

是不行的,因為

zone

沒有指派

zone 未指派的驗證

  • 進入

    runtime_default_zone

    的源碼實作
    iOS-底層原理 06:malloc 源碼分析 思路
  • 進入

    inline_malloc_default_zone

    的源碼實作,通過檢視

    malloc_zones

    的值發現是

    NULL

    ,可以得出,此時的

    zone還未指派

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

繼續跟蹤源碼

  • 回到

    default_zone_calloc

    方法,繼續執行,斷在

    zone->calloc

    部分,此時同樣可以通過上述的兩種方法任選其一進入 calloc的源碼實作

    nano_calloc

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

    nano_calloc

    方法,其中的關鍵代碼是 878,此時的p是pointer表示

    指針

    和前面的 ptr一樣,主要由兩部分邏輯
    • 如果要開辟的空間小于

      NANO_MAX_SIZE

      ,則進行則進行

      nanozone_t

      malloc

    • 反之,就進行

      helper_zone

      流程
      iOS-底層原理 06:malloc 源碼分析 思路
  • 進入

    _nano_malloc_check_clear

    源碼,将if else 折疊,看主流程
    • 其中

      segregated_next_block

      就是指針記憶體開辟算法,目的是找到合适的記憶體并傳回
    • slot_bytes

      是加密算法的

      (其目的是為了讓加密算法更加安全,本質就是一串自定義的數字)
      iOS-底層原理 06:malloc 源碼分析 思路
  • 進入

    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

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

    segregated_band_grow

    源碼,主要是開辟新的band
    iOS-底層原理 06:malloc 源碼分析 思路
先記錄libmalloc源碼中malloc分析的思路,需要時間研究源碼,後續再補充完善!!!

參考連結

  • iOS 進階之美(六)—— malloc分析