在iOS-底层原理2:alloc、init、new探析中,有介绍过alloc的三个核心方法,其中一个就是calloc,即申请内存,这一节,我们深入探究calloc如何开辟空间。
alloc核心方法
objc4中分析calloc 源码
打开objc4源码,跟着alloc流程 + alloc --> objc_rootAlloc --> callAlloc --> _objc_rootAllocWithZone --> _class_createInstanceFromZone进入到_class_createInstanceFromZone方法。
_class_createInstanceFromZone方法
点击calloc进入内部,只能看到calloc声明,无法进一步进行探索,怎么办?
下载libmalloc源码下载最新版,继续探索。
libmalloc中分析calloc源码
step1:打开libmalloc项目,新建一个Target
step2:在main中使用calloc创建一个指针
#import <Foundation/Foundation.h>
#import <malloc/malloc.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
void *p = calloc(1, 24);
NSLog(@"%p", p);
}
return 0;
}
step3:进入calloc源码
calloc实现
上述的default_zone是一个默认的空间大小,目的就是引导程序进入一个创建真正zone的流程; size是我们传入的空间的大小。
step4:进入malloc_zone_calloc
malloc_zone_calloc实现
- 其中
zone->calloc传入的zone就是 上一步中的default_zone - 这个关键代码的目的就是
申请一个指针,并将指针地址返回
step5:进入zone->calloc,发现command+鼠标并不能跳转到对应的实现
怎么办?
step6:在zone->calloc代码处打上断点,等程序执行到断点时,有两种方式可以查看zone->calloc源码实现;
1、按住control + step into,进入calloc的源码实现
2、在控制台输入lldb命令p zone->callocde查找源码实现
通过控制台查找zone->callocde源码
step7:全局搜索default_zone_calloc方法,找到具体实现
default_zone_calloc实现
step8:进入runtime_default_zone源码
runtime_default_zone实现
step9:进入inline_malloc_default_zone源码
inline_malloc_default_zone实现
查看malloc_zones的值发现是·NULL·,可以得出,此时的zone还未赋值
step10:回到default_zone_calloc源码,在zone->calloc处打上断点,继续执行,用在step6介绍的方式选其一
step11:全局搜索nano_calloc方法,进入源码
nano_calloc实现
step12:进入_nano_malloc_check_clear源码
_nano_malloc_check_clear实现
-
slot_bytes是算法的盐(本质是一串字符串,提升算法的加密安全性) -
segregated_next_block就是指针开辟算法,目的是找到合适的内存并返回
step13:进入segregated_size_to_fit源码
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) {
// NANO_REGIME_QUANTA_SIZE = 16
size = NANO_REGIME_QUANTA_SIZE; // Historical behavior
}
// SHIFT_NANO_QUANTUM = 4, (size+15) >> 4 (+15 右移4位)
k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quant
// << 4 (左移4位)
slot_bytes = k << SHIFT_NANO_QUANTUM; // multiply by power of two quanta size
*pKey = k - 1; // Zero-based!
return slot_bytes;
}
#define SHIFT_NANO_QUANTUM 4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) // 16
在iOS-底层原理5:内存对齐
中已经讲解过
step14:回到_nano_malloc_check_clear方法,进入segregated_next_block源码,这个方法主要就是获取内存指针
step15:第一次走segregated_next_block方法,band不存在,缓存也不存在,所以会调用segregated_band_grow,开辟新的band
segregated_next_block实现
暂时到此,后续再补充










网友评论