iOS开发之深入理解runtimeiOS

iOS开发之runtime(26):libmalloc入门

2019-03-31  本文已影响50人  kyson老师

本系列博客是本人的源码阅读笔记,如果有 iOS 开发者在看 runtime 的,欢迎大家多多交流。为了方便讨论,本人新建了一个微信群(iOS技术讨论群),想要加入的,请添加本人微信:zhujinhui207407,【加我前请备注:ios 】,本人博客http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

runtime logo

本文完整版详见笔者小专栏: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); 

那么

要解决这个问题,我们先抽丝剥茧,看看这个 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入门

上一篇下一篇

猜你喜欢

热点阅读