iOS開發之runtime(26):libmalloc入門

本系列博客是本人的源碼閱讀筆記,如果有 iOS 開發者在看 runtime 的,歡迎大家多多交流。爲了方便討論,本人新建了一個微信羣(iOS技術討論羣),想要加入的,請添加本人微信:zhujinhui207407,【加我前請備註:ios 】,本人博客http://www.kyson.cn 也在不停的更新中,歡迎一起討論


本文完整版詳見筆者小專欄:https://xiaozhuanlan.com/runtime

背景

maptable 中創建函數如下:

NXMapTable *NXCreateMapTableFromZone(NXMapTablePrototype prototype, unsigned capacity, void *z) {
    NXMapTable *table = (NXMapTable *)malloc_zone_malloc((malloc_zone_t *)z, 

之前我們沒有說過 malloc_zone_malloc 這個函數,今天我們大概瞭解一下。

分析

libmalloc
https://opensource.apple.com/tarballs/libmalloc/

函數 NXCreateMapTableFromZone 被調用的時機爲:

NXMapTable *NXCreateMapTable(NXMapTablePrototype prototype, unsigned capacity) {
    return NXCreateMapTableFromZone(prototype, capacity, malloc_default_zone());
}

因此,我們這裏調用 malloc_zone_malloc 將參數代入,可以改寫爲:

malloc_zone_malloc(malloc_default_zone(),sizeof(NXMapTable));

我們看一下該方法的定義:

void *
malloc_zone_malloc(malloc_zone_t *zone, size_t size)
{
    MALLOC_TRACE(TRACE_malloc | DBG_FUNC_START, (uintptr_t)zone, size, 0, 0);

    void *ptr;
    if (malloc_check_start && (malloc_check_counter++ >= malloc_check_start)) {
        internal_check();
    }
    if (size > MALLOC_ABSOLUTE_MAX_SIZE) {
        return NULL;
    }

    ptr = zone->malloc(zone, size);     // if lite zone is passed in then we still call the lite methods
    
    if (malloc_logger) {
        malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
    }

    MALLOC_TRACE(TRACE_malloc | DBG_FUNC_END, (uintptr_t)zone, size, (uintptr_t)ptr, 0);
    return ptr;
}

可見正常情況下應該會進入到代碼塊:

ptr = zone->malloc(zone, size); 

中。
也就是說

malloc_zone_malloc(malloc_default_zone(),sizeof(NXMapTable));

最終調用的調用結果是:

malloc_default_zone()->malloc(zone, size); 

那麼

  • 什麼是 default zone ?
  • 除了 default zone 還有其他什麼 zone ?

要解決這個問題,我們先抽絲剝繭,看看這個 malloc_default_zone() 的實現是怎麼樣的。源碼如下:

malloc_zone_t *
malloc_default_zone(void)
{
    return default_zone;
}

而 default_zone 的實現如下:

static virtual_default_zone_t virtual_default_zone
__attribute__((section("__DATA,__v_zone")))
__attribute__((aligned(PAGE_MAX_SIZE))) = {
    NULL,
    NULL,
    default_zone_size,
    default_zone_malloc,
    default_zone_calloc,
    default_zone_valloc,
    default_zone_free,
    default_zone_realloc,
    default_zone_destroy,
    DEFAULT_MALLOC_ZONE_STRING,
    default_zone_batch_malloc,
    default_zone_batch_free,
    &default_zone_introspect,
    10,
    default_zone_memalign,
    default_zone_free_definite_size,
    default_zone_pressure_relief,
    default_zone_malloc_claimed_address,
};

static malloc_zone_t *default_zone = &virtual_default_zone.malloc_zone;

棒!這個 __attribute__((section( 是不是特別熟悉!!!不熟悉的回顧文章:
iOS開發之runtime(16):設置/獲取section數據詳解
也就是說,virtual_default_zone 是在App啓動的時候就已經設置好值了。關於 default zone 筆者就討論到這裏了,更深層次的就不研究了,大家有興趣可以再去研究 libmalloc 的源碼。

完整版詳見筆者小專欄:iOS開發之runtime(26):libmalloc入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章