Object-C|对象原理(中) |
---|
我们继续探索alloc开辟内存空间
、绑定对象与isa
在计算出内存大小后,我们可以看到代码会继续往下走到maclloc_zone_calloc
\ calloc
中的其中一个,根据之前的方法可以找到,calloc
并不是objc
开源库中的,而是malloc
中的方法,那么我们就跟着方法继续探索malloc
开源库
malloc源码分析
我们编译好malloc
开源库后,就可以看到calloc
的内部实现是这个样子的
跟着方法中主要的流程继续跟下去,发现在maccoc_zone_calloc
方法中我们主要的ptr
对象已经跟不下去了,在这个时候我们可以使用另外的方法
通过LLDB打印得出ptr = zone->calloc
的方法其实是执行default_zone_calloc
方法
再继续跟住
按照流程会来到这里,发现又断开了
根据之前的经验,运用技巧发现它其实会走到nano_malloc
方法
最终走到了这个方法里面进行对象的内存开辟
总结:其实我们做了很多没有什么新的实质内容的事情,一直在跟方法流程,但是从中我们学会了解决就算我们拿到了开源库有时候也会因为被代码逻辑纠缠住找不到重点,从而跟不下去的问题。跟代码其实不重要 ,掌握学习的方法很重要
Isa关联
继开辟空间后
我们得到了内存地址指针isa
但是这个时候打印输出我们的对象发现还会是null
其原因就是并没有将isa
和对象
进行关联
其内部实现方法
再继续跟到initIsa
,发现isa
其实就是isa_t
的返回,也就是结构体
isa_t
使用了联合体位域
来优化内存空间
在判断是否nonpointerIsa
后进入到else
来进行对象
与isa绑定
、类信息填充
tips
对象的本质就是结构体
isa结构信息
Isa
8字节
64位
64位
中包含了很多的内容
nonpointer
表示是否对isa开启指针优化,0 纯isa
指针、1 不止是类对象
地址,isa
包含了类信息
、对象的引用计数
等
has_assoc
关联对象标识为,0 没有、1存在
has_cxx_dtor
该对象是否有c++
或者Objc
的析构器,如果有析构函数
则需要做析构逻辑
,如果没有则更快的释放对象
shiftcls
存储类指针的值。开启指针优化的情况下,在arm64
架构中有33位
用来存储类指针
Magic
用于调试器判断当前对象是真的对象还是没有初始化的空间
weakly_referenced
指对象是否被只想或曾经只想一个ARC
的弱变量,没有若引用的对象可以更快释放
deallocating
标志对象是否正在释放内存
has_sidetable_rc
当对象引用计数大与10时,则需要借用该变量存储进位
extra_rc
当表示该对象的引用计数值,实际上引用计数值减1,例如:如果对象的引用计数为10,那么extra_rc
为9,如果引用计数大于10,则需要使用到has_sidetable_rc
tips:
1、通过对象的指针地址与
isa_t
的mask
去&
出该指针地址绑定的类信息
2、通过指针地址所代表的机器码>>3 <<20 >>17
来反算(arm64
的情况下)
3、直接用runtime
下的object_getClass
方法
结构体与联合体位域
(1)结构体
struct
结构体是指把不同的数据合成一个整体,其变量是共存关系
,变量不管是否使用都会分配内存。缺点:所有属性都分类内存,比较浪费。优点:存储容量大
,包容性强
,成员之间不会相互影响
(2)联合体位域union
联合体也是由不同的数据类型组成,但其变量是互斥关系
,所有的成员占用一段内存。而且共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来的成员的值覆盖掉。缺点:包容性差
优点:所有成员共用一段内存 ,使内存的使用更加精细灵活,同时也节省了内存空间
Object-C|类原理 |
---|