iOS 底层原理之alloc探究

Posted WeaterMr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 底层原理之alloc探究相关的知识,希望对你有一定的参考价值。

ios 底层原理之alloc 探究(一)

结论先行:

当初始一个对象[[Goods alloc] init] ,其中alloc方法主要通过_class_createInstanceFromZone 方法 做三件事 :
1.instanceSize (计算需要申请的内存大小)
2.calloc (向系统申请开辟内存,返回地址指针)
3.initInstanceIsa (通过isa 绑定相应的类)
说白了,就好比你是厂长,你告诉仓库管理员现在有一批货物要入库。
管理员首先看看这批货物有多少要多大的房间,
其次找到对应大小的房间,拿到该房间的钥匙,
最后在钥匙上打上标签。然后在将钥匙给到你。

文章主要内容:定位_class_createInstanceFromZone函数源码与解析
一.如何找到 _class_createInstanceFromZone?
1)找到对应的源码出处

这里提供一种常用方式:通过汇编跟流程加符号断点的方法。
操作步骤:1.在这里插入图片描述
选择 Always Show Disassembly (以汇编的形式显示堆栈信息)
将进入下面页面
在这里插入图片描述
2.按住control键,然后step into 进入下一步将进入到下面界面
在这里插入图片描述

这时我们将看到当前调用的函数方法:objc_alloc_init 方法
3.通过符号断点方法再次运行代码如下图在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这时我们将看到 objc_alloc_init 是属于libobjc动态库的函数方法。

2)下载源码 objc4-818.2大牛编译好的)-编译源码-分析原码

1.通过断电调试源代码如下图:
请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
当手动通过方法进入的时流程:通过汇编跑流程我们可以发现会先走这个流程: alloc —>objc_alloc—>
_objc_rootAllocWithZone—>objc_msgSend

然后在走真正的内存 申请流程 :alloc —> _objc_rootAlloc —>callAlloc —>_objc_rootAllocWithZone—>_class_createInstanceFromZone
那为什么会走两遍 alloc 方法呢? 个人猜测其实第一遍类似于网络请求的三次握手,相当于对象在开辟内存是有一个预计算流程。通过断电可以发现,只要走alloc 方法,都会有两遍。因为alloc 方法是直接对内存进行操作,所以加一成hook很正常。也就是我要先知道你申请的内存够不够,能不能申请。
当跟者汇编 - control + step into 跑程序时可能会出现跳方法的情况,牵扯到编译器优化

二._class_createInstanceFromZone 函数解析

1) “ c l s − > i n s t a n c e S i z e ” \\color{orange}{“cls->instanceSize ” } cls>instanceSize : 先计算出需要的内存空间大小
“ 问 题 : 对 象 的 内 存 大 小 和 什 么 有 关 ? ” \\color{red}{“问题 :对象的内存大小和什么有关?” }
只和成员变量有关和其他没有任何关系。

inline size_t instanceSize(size_t extraBytes) const {
//快速计算内存大小
if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
return cache.fastInstanceSize(extraBytes);
}
// “ e x t r a B y t e s ” \\color{red}{“extraBytes ” } extraBytes : 计算对象中所有成员变量需要的内存大小 (当该类不存在成员变量时默认为0
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
//最小返回16字节
“ 问 题 : 为 什 么 需 要 16 字 节 对 齐 ? ” \\color{red}{“问题:为什么需要16字节对齐?” } 16
cpu 读取数据以固定字节块来读取可以提高cpu的性能和读取速度(空间换时间)。
if (size < 16) size = 16;
return size;
}

2) “ c a l l o c ” \\color{orange}{“calloc ” } calloc: 向系统申请开辟内存,返回地址指针
根据第一步计算出的大小向系统申请开辟内存,返回地址指针

3) “ o b j − > i n i t I n s t a n c e I s a ” \\color{orange}{“obj->initInstanceIsa ” } obj>initInstanceIsa:关联到相应的类

inline void
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
ASSERT(!cls->instancesRequireRawIsa());
ASSERT(hasCxxDtor == cls->hasCxxDtor());
initIsa(cls, true, hasCxxDtor);
}
通过isa将对应的内存关联到对应的类。
到此alloc底层原理探究先告一段落。后续。。。

以上是关于iOS 底层原理之alloc探究的主要内容,如果未能解决你的问题,请参考以下文章

iOS底层原理之alloc探究对象本质与神秘的isa

iOS 底层探究之 alloc

iOS开发底层之alloc原理初探

iOS 底层原理 + 逆向 文章汇总

iOS底层原理 - Block本质探究

iOS底层原理-KVO本质探究