美文网首页
iOS calloc

iOS calloc

作者: 唱歌的鼻涕泡 | 来源:发表于2021-08-06 18:03 被阅读0次
    calloc

    浅究 calloc

    oc 代码中的 alloc 主要有三种作用 1、计算分配内存大小(字节对齐)2、向系统申请内存,并开辟 3、 绑定iSA指针

    研究了 系统在没有优化的情况下的分配内存情况,那么现在研究一下 OC源码中是怎样向系统申请空间的

    源码

    1、一如即往的我们打开源码 走一走

        id obj;
        if (zone) {
            obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
        } else {
            obj = (id)calloc(1, size);
        }
    

    不知不觉的又走到了巷子口,呸,关键口,我这边是一直都会走到
    obj = (id)calloc(1, size);
    那么我们去看看 calloc 到底做了什么!

    calloc
    void *
    calloc(size_t num_items, size_t size)
    {
        return _malloc_zone_calloc(default_zone, num_items, size, MZ_POSIX);
    }
    

    给它两个入参,一个是开辟的个数,一个是开辟的大小,就是上面 字节对齐,优化后 的 内存开辟的大小

    size = cls->instanceSize(extraBytes);
    
    _malloc_zone_calloc
    MALLOC_NOINLINE
    static void *
    _malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size,
            malloc_zone_options_t mzo)
    {
        MALLOC_TRACE(TRACE_calloc | DBG_FUNC_START, (uintptr_t)zone, num_items, size, 0);
    
        void *ptr;
        if (malloc_check_start) {
            internal_check();
        }
        ptr = zone->calloc(zone, num_items, size);
    
        if (os_unlikely(malloc_logger)) {
            malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE | MALLOC_LOG_TYPE_CLEARED, (uintptr_t)zone,
                    (uintptr_t)(num_items * size), 0, (uintptr_t)ptr, 0);
        }
    
        MALLOC_TRACE(TRACE_calloc | DBG_FUNC_END, (uintptr_t)zone, num_items, size, (uintptr_t)ptr);
        if (os_unlikely(ptr == NULL)) {
            malloc_set_errno_fast(mzo, ENOMEM);
        }
        return ptr;
    }
    

    走到这一步,看的里面眼花缭乱了,分不清哪个是主线任务了,经验告诉我,许多判断语句里面是存放的标识位,那么我们着重看一看

    ptr = zone->calloc(zone, num_items, size);
    

    只有这个是对新 变量赋值的,不要怀疑了,我确实是预言家。

    可是 不难发现,这又回去了,又是来到了一个 calloc

    注释 p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员

    不难看出zone 是一个指针 指向了 calloc(zone, num_items, size);
    那么我们打印一下这个指针


    打印指针

    这算是一个小技巧吧,p 一下 生成的过程 ,结果惊喜的发现了 走的类名字
    default_zone_calloc

    那我走~~,走到这个default_zone_calloc 里面瞧一瞧吧

    default_zone_calloc
    static void *
    default_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size)
    {
        zone = runtime_default_zone();
        
        return zone->calloc(zone, num_items, size);
    }
    

    神奇的事情又发生了,它继续走到了
    return zone->calloc(zone, num_items, size);
    照葫芦画瓢,咱们再试试 p zone->calloc


    nano_calloc

    发现了新的线索

    nano_calloc
    static void *
    nano_calloc(nanozone_t *nanozone, size_t num_items, size_t size)
    {
        size_t total_bytes;
    
        if (calloc_get_size(num_items, size, 0, &total_bytes)) {
            return NULL;
        }
    
        if (total_bytes <= NANO_MAX_SIZE) {
            void *p = _nano_malloc_check_clear(nanozone, total_bytes, 1);
            if (p) {
                return p;
            } else {
                /* FALLTHROUGH to helper zone */
            }
        }
        malloc_zone_t *zone = (malloc_zone_t *)(nanozone->helper_zone);
        return zone->calloc(zone, 1, total_bytes);
    }
    

    哇 又来到了一个新世界,继续根据线索走
    可以发现 第一行

       if (calloc_get_size(num_items, size, 0, &total_bytes)) {
            return NULL;
        }
    

    这是一个容错处理

    malloc_zone_t *zone = (malloc_zone_t *)(nanozone->helper_zone);
    

    下面这个是helper 一般带有help的 都不是主线任务,辅助要carry 太难了

    void *p = _nano_malloc_check_clear(nanozone, total_bytes, 1);
    

    排除了这么老半天终于察觉到了这行代码嫌疑最大,开整

    _nano_malloc_check_clear

    这里面开始 对 内存又进行了一步 16字节对齐
    其中的核心代码是

    ptr = segregated_next_block(nanozone, pMeta, slot_bytes, mag_index);
    

    Note slot_key is set here 这里为哈希算法的盐

    segregated_size_to_fit

    这个代码里面就是奇妙所在了,这正是要做的 16字节对齐的关键

    static MALLOC_INLINE size_t
    segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey)
    {
        size_t k, slot_bytes;
    
        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 calloc

          本文链接:https://www.haomeiwen.com/subject/nmmuvltx.html