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探究的主要内容,如果未能解决你的问题,请参考以下文章