项目准备
苹果开源源码汇总: https://opensource.apple.com
这个地址⽤的更直接 https://opensource.apple.com/tarballs/
到这里下载objc的源码进行解析
开始:
首先来看一组打印
例如,一下情况打印的内存地址输出是一样
![](https://img.haomeiwen.com/i9276618/96dc15e0a9092086.png)
说明alloc开辟了内存空间,init并没有开辟内存空间
alloc又是怎么开辟内存的呢?继续往下
首先来看一张图开辟空间执行顺序
![](https://img.haomeiwen.com/i9276618/198999f31336220f.png)
通过源码我们一步一步往里面走
1.alloc调用了_objc_rootAlloc
![](https://img.haomeiwen.com/i9276618/7de170b94a982116.png)
2._objc_rootAlloc方法中调用了callAlloc方法,但是由于编译器的优化,callAlloc并没有走
![](https://img.haomeiwen.com/i9276618/61710c9e94c670b8.png)
3.callAlloc调用_objc_rootAllocWithZone
![](https://img.haomeiwen.com/i9276618/15030abd3175bfee.png)
4_objc_rootAllocWithZone调用_class_createInstanceFromZone
1).cls->instanceSize计算开辟内存空间的大小
点进去方法发现得到的内存是16
![](https://img.haomeiwen.com/i9276618/ecc4207f9cebc142.png)
系统在开辟内存的时候是内存对齐的,都是16的倍数,为了更快和安全
每个对象分配出来都会包含一个isa,isa就会占8个字节,如果只是分配8个字节的话,每一个创建出来的对象都会紧挨着前一个对象,所以很容易出现野指针,访问内存错误等问题,而16字节是留出来了预留字节,这样每次访问的时候会相对于更加安全
2).calloc 向系统申请内存,返回地址指针
![](https://img.haomeiwen.com/i9276618/b521b3b0300b92d9.png)
图上方法走之前,obj是nil,但是当方法走了以后,会返回一个地址指针,但是这个地址指针并没有关联到我们的类上面
3).obj->initInstanceIsa关联到对象
![](https://img.haomeiwen.com/i9276618/a76b3679f6ec60f5.png)
上图方法走之前打印obj可以看到只是一个地址,并没有输出我们的类
![](https://img.haomeiwen.com/i9276618/72dfcd793ccb05aa.png)
但是当走了obj->initInstanceIsa方法以后,我们再次打印发现
![](https://img.haomeiwen.com/i9276618/0857ab5425390969.png)
此时我们的类名已经关联到了指针上面
![](https://img.haomeiwen.com/i9276618/b787cd72aee14f5e.png)
然后返回我们的对象
网友评论