iOS Runtime 数据结构

ios内存布局

内存管理方案

数据结构

ARC & MRC

引用计数

弱引用

自动释放池

循环引用

ios内存布局

  • stack: 方法调用
  • heap: alloc后的实力
  • bss: 未初始化的全局变量
  • data: 已经初始化的全局变量
  • text:程序代码

内存管理方案

iOS操作系统是怎么内存管理,要根据场景去回答。

  • TaggedPointer: 小数据number
  • NONPinter_ISA: 64位置中有内训管理的东西32位永不玩
  • 散列表:弱引用表,引用技术表
  • NONPinter_ISA:
    arm64架构
    0 0 0 0 0 0 0 0 0 0 (has_cxx_dtor) 0(has_assoc) 0(index: 0代表一个纯isa指针,)
    然后32位是关于isa地址的
    弱引用weakly_referenced
    散列表
    extrac_rc 存储引用计数值

  • 散列表
    side tables()结构
    是一个哈希表里面有:
    自旋锁
    引用计数表
    弱引用表

为什么不是一个Side Table?而是多个?
是在多线程下,一张表放了成千上万,就要锁住,就有效率的问题。
分离锁,要用多张表,就是能提高效率。

  • 怎么实现快速分流?
    SideTables的本质是一张Hash表
    Key(对象指针) — hash函数(Hash查找) — Value(side Table)

  • Hash查找
    取余运算
    通过hash查找,是为了节约效率。不涉及到遍历查找

  • 数据结构

  1. spinlock_t
    是一种忙等的锁。
    适用于轻量的访问,比如+1 和 -1操作

  2. 引用计数表
    refcountMap 是hash表,可以理解成一个字典,Hash查找是为了提高效率,插入和获取都是一个函数确定的。避免循环读遍历

  3. size_t
    是否若应用,石头在dealloc

  4. 弱引用表
    weak_table_t 也是hash表

  • MRC

什么是MRC,手动引用计数
alloc 分配内存空(只能MRC调用)

retain +1
ralease -1
retainCount
autoralease 在自动释池结束后-1

dealloc (要用supper 调用去废弃父类的一些东西)(只能MRC调用)

  • ARC
    自动引用计数,编译器自动的插入retain ralease操作
  1. ARC是编译器和runTime协作结果
  2. ARC 不能调用 ratain release retainCount dealllic
  3. ARC中新增wack、strong关键字

引用计数管理

  • alloc实现,最终是调用了C函数calloc,在alloc之初并没有调用ratian但是,rataincongt是1

  • retain实现

    1. 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
    2. 最终获得size_t这个64个bit的
    3. 最终偏移两位在操作
  • release

    1. 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
    2. 最终获得size_t这个64个bit的
    3. 最终偏移两位在操作
  • retainCont

    1. 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
    2. 声明一个局部变量是1
    3. 在查找后和1合并
  • dealloc
    调用rootDealloc,判断时候可以释放,判断条件
    nonpointer_isa
    weak_referenced
    has_assoc
    has_cxx_dtor
    has_sidetable_rc

都不满足 free()

不是的话dispose操作

  • dispose操作是高那些额外的东西:
    destraucInstan()函数中判断和销毁一些东西,
  1. 是否用gCxx的东西
  2. 是否有关联对象,有的话移除掉
  3. clearDeallocing()
    • 将指向改对象的弱引用的指针置成nil
    • 在引用计数表中擦除掉该对象的引用计数

然后再去调用cfree()

弱引用管理

添加弱引用变量?
hash算法查找到弱引用数组

清除weak变量,同时指向nil?
dealloc操作后 weak_clear_no_lock中,当前对象指针查找弱引用表,对弱引用数组进行操作。

自动释放池

  • autoreleasePool的是什么原理?
    autoreleasePool为什么可以嵌套使用?

@autorealeasepool编译器的改为:

autorealeasepool是以栈为节点,通过双向链表的形式组合而成的
是和线程一一对性的

  • 双向链表
  • 双向表

  • 后入先出,高地址到低地址

在档次runloop简要结束的时候条用AutoreleasePoolOage::POP
多次嵌套就是多次插入哨兵对象
在for循环中alloc图片输入数据内存系哦啊好较大的场景手动插入autoreleasePool

循环引用

  • 循环引用类型
  1. 自循环引用
  2. 相互循环应用
    3.多对象循环应用
  • 重点
    1.代理(相互循环引用)
  1. Block
  2. NSTimer
  • 如何破除训话引用?
  1. 避免产生循环引用(强弱)
  2. 适当时机手动断环
  • 解决方法呢
    __weak
    __block
    __unsafe_unretained

  • __block破解

  1. 在MRC下, __修饰的对象不会增加其引用计数,避免了循环引用
  2. ARC下,__block修饰的对象会被强引用,无法避免循环引用,要手动解环。
  • __unsafe_unretained
  1. 修饰的对象不会增加其引用计数,避免了循环引用。
  2. 如果被修饰的对象在某以实际被释放,会产生悬垂指针。

*循环引用的示例
在平时开发中有没有遇到循环引用,你是怎么解决的。

  1. block的使用示例
  2. NSTimer的是示例

*NSTimer的训话引用问题

VC持有轮播器,要添加对象,对象和NStimer是互相强引用。

NSTimer会被Runloop强引用,所以弱引用没有用。
非重复的NSTimer中,Timer结束之后的回调中,invalid和置为nil

如果是重复的NSTimer,中间使用以个中间对象,中间对象对NStimer和对象弱引用,而NSTimer对中间对象强引用。
下次NStimer回来判断对象是否配释放了

  • 内存管理总结
    什么是ARC,VVLM编译器和Runtime协作管理?

为什么weak指针指向的对象在废弃之后会被置为nil?
苹果是什么实现AutoReleasePool的?
什么和怎么避免循环引用?

你可能感兴趣的:(iOS Runtime 数据结构)