在iOS-底层原理2:alloc、init、new探析中,有介绍过alloc
的三个核心方法,其中一个就是calloc,即申请内存,这一节,我们深入探究calloc如何开辟空间。
objc4中分析calloc 源码
打开objc4源码,跟着alloc
流程 + alloc
--> objc_rootAlloc
--> callAlloc
--> _objc_rootAllocWithZone
--> _class_createInstanceFromZone
进入到_class_createInstanceFromZone
方法。
点击calloc
进入内部,只能看到calloc声明,无法进一步进行探索,怎么办?
下载libmalloc源码下载最新版,继续探索。
libmalloc中分析calloc源码
step1
:打开libmalloc
项目,新建一个Target
step2
:在main
中使用calloc
创建一个指针
#import
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
void *p = calloc(1, 24);
NSLog(@"%p", p);
}
return 0;
}
step3
:进入calloc
源码
上述的default_zone
是一个默认的空间大小,目的就是引导程序进入一个创建真正zone的流程; size是我们传入的空间的大小。
step4
:进入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
查找源码实现
step7
:全局搜索default_zone_calloc
方法,找到具体实现
step8
:进入runtime_default_zone
源码
step9
:进入inline_malloc_default_zone
源码
查看malloc_zones
的值发现是·NULL·,可以得出,此时的zone还未赋值
step10
:回到default_zone_calloc
源码,在zone->calloc处打上断点,继续执行,用在step6
介绍的方式选其一
step11
:全局搜索nano_calloc
方法,进入源码
step12
:进入_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
暂时到此,后续再补充