内存管理-retain&realese

1,199 阅读2分钟

在分析 retainrealese 之前我们先了解一下 nonPointerIsanonPointerIsa 代表非指针,代表 isa 的结构,在相关位置处理上与 TaggedPointer 具有相似性,都涉及到位运算等,但是它们是完全不同的东西,TaggedPointer 是对相关对象类型的处理。

nonPointerIsa 的详细介绍大家可以看 iOS 对象探究三 这篇文章,下面是 x86 64位 系统下 isa 位域信息的介绍。

x86 64位下 isa 位域信息.png

// nonpointer 表示是否对 isa 指针开启指针优化 0:纯isa 指针,1:不止是类对象地址,isa 中包含了类信息, 对象的引用计数等
// has_assoc 关联对象标志位,0:没有,1:存在
// has_cxx_dtor 该对象是否有 C++或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象。
// shiftcls 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位用来存类指针。
// magic:用于调试器判断当前对象是真的对象还是没有初始化的空间。
// weakly_referenced 表示对象是否被指向或者曾经指向一个 ARC 的弱变量,没有弱引用的对象可以更快释放。
// deallocating:标志对象是否正在释放内存
// unused 是否使用散列表
// has_sidetable_rc:当对象引用计数大于 10 时,则需要借用该变量存储进位
// extra_rc: 当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。

retain

image.png image.png image.png

retain 流程总结:

  1. 判断是否是 isTaggedPointer 类型
  2. 判断是否是 nonpointer 2.1 不是的话就直接操作散列表,对引用计数加一 2.2 判断是否正在释放,在的话不往下处理 2.3 newisa.bits 左移 45 位加一 2.4 判断是否超出范围,超出的话对数组除 2,extra_rc 存一半的值,散列表存一半。这个地方这样做是为了效率问题考虑,如果都存到散列表的话减减的时候需要操作散列表,需要开表查表,比较消耗性能。

realese

image.png image.png

realese 流程总结:

    1. 判断是否是 isTaggedPointer 类型
    1. 判断是否是 nonpointer
  • 2.1 不是的话就直接操作散列表,对引用计数减一
  • 2.2 判断是否正在释放,在的话不往下处理
  • 2.3 是 nonpointer 的话就对 extra_rc 的数值进行减减
  • 2.4 判断减减是否超出范围,超出的话判断是否有散列表,有的话就取出散列表中值的一半赋值给 extra_rc ,并对散列表的值进行更新。
    1. extra_rc 与散列表中的值都为 0,或者没有散列表的时候就对对象发送 dealloc 消息,进行析构。