iOS 底层原理 文章汇总
在iOS-底层原理 02:alloc & init & new 源码分析文章中,
alloc
有3个核心操作,其中一个就是
calloc
,即申请内存,这就是今天需要探索的内容,其实探索的本质也是为了验证
ios中对象中实际的对齐方式是8字节对齐
objc4中分析calloc 源码
- 首先从alloc进入objc的源码,找到
操作,涉及的方法顺序是obj = (id)calloc(1, size);
alloc --> _objc_rootAlloc --> callAlloc --> _objc_rootAllocWithZone --> _class_createInstanceFromZone
这里calloc的探索需要切换到
libmalloc
源码中,可以在这里下载最新版,接着往下走
libmalloc中分析calloc源码
- 在可编译的libmalloc中定义一个可编译的target,在main中使用
创建一个指针calloc
- 进入calloc的源码实现,其中的关键代码在于
1713行的 malloc_zone_calloc
- 其中
是一个默认的zone,目的就是引导程序进入一个创建真正default_zone
的流程zone
- 其中
- 进入
的源码实现,关键代码是1441行的malloc_zone_calloc
zone->calloc
- 其中
传入的zone 就是 上一步中的zone->calloc
default_zone
- 这个关键代码的
就是目的
申请一个指针,并将指针地址返回
- 其中
- 在进入
的源码,发现是一个zone->alloc
的声明,到此,源码就无法继续跟进了calloc
那么重点来了!!!想要继续跟进源码,可以通过以下方式:
- 在
中的关键代码,即malloc_zone_calloc
处,加一个断点,然后运行ptr = zone->calloc(zone, num_items, size);
- 断点断在 ptr位置,想要进入zone->calloc源码实现,有两种方式:
- 按住
+control
,进入step into
的源码实现calloc
- ,然后通过lldb命令
查找源码实现,通过打印得知p zone->callocde
的源码实现在zone->calloc
方法,然后全局搜索default_zone_calloc
方法,找到具体实现default_zone_calloc
- 按住
- 进入calloc的源码实现,其中主要由两部分操作
- 创建真正的
,即zone
方法runtime_default_zone
- 使用真正的
进行zone
calloc
- 创建真正的
断点断在zone的位置,此时通过lldb命令
p zone->alloc
是不行的,因为
zone
还
没有赋值
zone 未赋值的验证
- 进入
的源码实现runtime_default_zone
- 进入
的源码实现,通过查看inline_malloc_default_zone
的值发现是malloc_zones
,可以得出,此时的NULL
zone还未赋值
继续跟踪源码
- 回到
方法,继续执行,断在default_zone_calloc
部分,此时同样可以通过上述的两种方法任选其一进入 calloc的源码实现zone->calloc
nano_calloc
- 进入
方法,其中的关键代码是 878,此时的p是pointer表示nano_calloc
和前面的 ptr一样,主要由两部分逻辑指针
- 如果要开辟的空间小于
,则进行则进行NANO_MAX_SIZE
的nanozone_t
malloc
- 反之,就进行
流程helper_zone
- 如果要开辟的空间小于
- 进入
源码,将if else 折叠,看主流程_nano_malloc_check_clear
- 其中
就是指针内存开辟算法,目的是找到合适的内存并返回segregated_next_block
-
是加密算法的slot_bytes
(其目的是为了让加密算法更加安全,本质就是一串自定义的数字)盐
- 其中
- 进入
加密算法源码, 通过算法逻辑,可以看出,其本质就会16字节对齐算法segregated_size_to_fit
#define SHIFT_NANO_QUANTUM 4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) // 16
static MALLOC_INLINE size_t
segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey)
{
size_t k, slot_bytes;
//k + 15 >> 4 << 4 --- 右移 + 左移 -- 后4位抹零,类似于16的倍数,跟 k/16 * 16一样
//---16字节对齐算法,小于16就成0了
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-底层原理 05:内存对齐原理文末,已经提及过该算法,这里不再过多说明
- 回到
方法,进入_nano_malloc_check_clear
源码,这个方法主要就是segregated_next_block
获取内存指针
- 但是如果是第一次走到
函数,band不存在,缓存也不会存在,所以会调用segregated_next_block
,来开辟新的segregated_band_grow
band
- 但是如果是第一次走到
- 进入
源码,主要是开辟新的bandsegregated_band_grow
先记录libmalloc源码中malloc分析的思路,需要时间研究源码,后续再补充完善!!!
参考链接
- iOS 高级之美(六)—— malloc分析