iOS之alloc底层实现分析

337 阅读2分钟

作为一名iOS多年开发经验的程序员,写了不少从0~1的项目,总觉得自己已经掌握的差不多,可是出去面试的时候,每次被问倒的往往是那些看起来并不起眼的地方。 相信作为一个iOS开发人员,大家对于alloc方法并不陌生,但是问你alloc具体做了什么,底层如何实现的,我相信不少同学回答不上来了,接下来我就带大家一起探索下alloc的底层实现。
新建工程,建立一个类Student,继承NSObject。
通常情况下,我们查看一个方法的实现,是通过按住command+点击要查看的方法,按照这种方式去点击alloc方法,会发现根本看不到alloc里面具体调了什么方法,每个方法都做了什么。

准备资料

objc4-818.2源码(已经补上,源码可运行):

链接: pan.baidu.com/s/1xt2YuoZm…
提取码: ov85 --来自百度网盘超级会员v3的分享

查看alloc实现的三种方式

查看方式一:通过step into
1、control + step into control + step into.png

2、可以看到调用了这个方法.png 如果发现,步骤1操作没反应,建议多点几下就可以进去了

查看方式二:直接下断点符号alloc

alloc符号断点.png

alloc符号断点2.png 如图所示,alloc会调用_objc_rootAlloc方法

查看方式三:查看汇编(推荐这种)
Xcode菜单栏-》debug -》 debug workflow -》 always show disassembly。

然后运行可以看到objc_alloc

2-1.png

以上三种方式操作繁琐,效率可见度比较低,接下来推荐一种比较直观且方便的方式:源码编译。

1、打开下载好的源码工程objc,搜索"alloc {" 可以看到alloc的实现
alloc -》_objc_rootAlloc -》callAlloc -》 _objc_rootAllocWithZone(或Objc_msgSend)-》_class_createInstanceFromZone

alloc底层实现流程图.png
2、核心的实现就在_class_createInstanceFromZone这个方法里,接下来我们就着重分析这个方法: 为了方便分析,请在下图几个地方打上断点
分析源码之下断点.png

2.1、instanceSize:申请要开辟的内存空间大小 分析源码之instanceSize.png 补充:对象的内存大小只和成员变量有关系。

2.2、calloc:根据instanceSize返回值开辟内存空间
calloc执行前后都在控制台执行打印命令po obj
通过对比calloc前后打印的obj内容,可以看到obj的地址发生了改变,那么为什么这里会有两个地址呢?其实calloc之前的地址属于废地址,calloc之后的地址才是真正开辟的地址。眼尖的同学可能发现,控制台并没有打印obj的类型,那是因为这个时候,并没有对obj进行isa的指向。

2.3、initInstanceIsa:将类和开辟的空间进行isa绑定
此刻再打印obj可以看到,obj类型已经打印出来了。
解释下initInstanceIsa方法的参数:
参数1是绑定isa指向; 参数2是绑定 c++的一些函数信息。