iOS - alloc&init底层初探
首先,我们来看一段代码:

可以看到p1,p2,p3输出地址完全相同,由此我们不难得出alloc其实已经创建了对象,那么alloc是如何创建对象的呢?init又做了哪些事呢?且随笔者慢慢挖掘alloc本质.
一、如何查看alloc的底层实现
注:由于模拟器与真机运行环境不同,此处需真机调试.
1.1通过直接下断点的方式


至此我们可以看到objc_alloc 在libobjc.A.dylib动态库中;
1.2通过sumbolic Breakpoint方式添加断点


之后我们依旧会进入到下面界面

1.3通过汇编方式查看


找到objc_alloc下断点 按住control点击Step into 依旧会进到下面界面

由以上三种方法我们可以看出objc_alloc 在libobjc.A.dylib动态库中,接下来我们就看一下alloc的具体实现方式.
二、alloc源码分析
2.1配置objc4-756.2 具体配置请参考iOS_objc4-756.2 最新源码编译调试
2.2追踪alloc实现流程
1、点击查看alloc在NSObject中的实现方法;

2、查看_objc_rootAlloc内部实现方法,发现此时返回一个callAlloc对象;

3、查看callAlloc内部实现发现canAllocFast()方法调用的bits.canAllocFast()返回的固定值为false,因此势必会走else中class_createInstance方法;

4、查看class_createInstance实现,其内部调用了_class_createInstanceFromZone方法,并在_class_createInstanceFromZone方法中进行size计算,内存申请,以及isa初始化;

_class_createInstanceFromZone内部实现:

5、计算size大小,通过方法cls->instanceSize(extraBytes),计算出size,其中64位系统下,对象大小采用8字节对齐;

但是实际申请的内存最低为16字节,即当小于16个字节时,系统分配16个字节;

6、根据zone的条件判断使用calloc或malloc_zone_calloc开辟内存空间,并将obj对象返回;

三、init源码分析

通过源码我们发现init其实什么也没做,init的作用其实是一种工厂模式,便于开发者对init方法进行重新,已实现自己想要实现的效果.
四、new源码分析

通过new的源码我们不难看出,new先调用callAlloc创建对象,并调用init方法,即[class new]相当于[[class alloc] init];
五、总结
1、alloc创建了对象并且申请了一块不少于16字节的内存空间;
2、init是一种开发者模式-工厂模式,便于开发者进行自定义修改;
3,new方法相当于alloc+init.
附:alloc流程图

注:如有错误的地方,万望斧正!
网友评论