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查找,是为了节约效率。不涉及到遍历查找数据结构
spinlock_t
是一种忙等的锁。
适用于轻量的访问,比如+1 和 -1操作引用计数表
refcountMap 是hash表,可以理解成一个字典,Hash查找是为了提高效率,插入和获取都是一个函数确定的。避免循环读遍历size_t
是否若应用,石头在dealloc弱引用表
weak_table_t 也是hash表
- MRC
什么是MRC,手动引用计数
alloc 分配内存空(只能MRC调用)
retain +1
ralease -1
retainCount
autoralease 在自动释池结束后-1
dealloc (要用supper 调用去废弃父类的一些东西)(只能MRC调用)
- ARC
自动引用计数,编译器自动的插入retain ralease操作
- ARC是编译器和runTime协作结果
- ARC 不能调用 ratain release retainCount dealllic
- ARC中新增wack、strong关键字
引用计数管理
alloc实现,最终是调用了C函数calloc,在alloc之初并没有调用ratian但是,rataincongt是1
-
retain实现
- 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
- 最终获得size_t这个64个bit的
- 最终偏移两位在操作
-
release
- 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
- 最终获得size_t这个64个bit的
- 最终偏移两位在操作
-
retainCont
- 当前对象的指针,sideTables找到sideTable,在sideTable中找到当前对象的引用计数表,这是两次hash查找。
- 声明一个局部变量是1
- 在查找后和1合并
dealloc
调用rootDealloc,判断时候可以释放,判断条件
nonpointer_isa
weak_referenced
has_assoc
has_cxx_dtor
has_sidetable_rc
都不满足 free()
不是的话dispose操作
- dispose操作是高那些额外的东西:
destraucInstan()函数中判断和销毁一些东西,
- 是否用gCxx的东西
- 是否有关联对象,有的话移除掉
- clearDeallocing()
- 将指向改对象的弱引用的指针置成nil
- 在引用计数表中擦除掉该对象的引用计数
然后再去调用cfree()
弱引用管理
添加弱引用变量?
hash算法查找到弱引用数组
清除weak变量,同时指向nil?
dealloc操作后 weak_clear_no_lock中,当前对象指针查找弱引用表,对弱引用数组进行操作。
自动释放池
- autoreleasePool的是什么原理?
autoreleasePool为什么可以嵌套使用?
@autorealeasepool编译器的改为:
autorealeasepool是以栈为节点,通过双向链表的形式组合而成的
是和线程一一对性的
- 双向链表
- 双向表
- 栈
后入先出,高地址到低地址
在档次runloop简要结束的时候条用AutoreleasePoolOage::POP
多次嵌套就是多次插入哨兵对象
在for循环中alloc图片输入数据内存系哦啊好较大的场景手动插入autoreleasePool
循环引用
- 循环引用类型
- 自循环引用
- 相互循环应用
3.多对象循环应用
- 重点
1.代理(相互循环引用)
- Block
- NSTimer
- 如何破除训话引用?
- 避免产生循环引用(强弱)
- 适当时机手动断环
解决方法呢
__weak
__block
__unsafe_unretained__block破解
- 在MRC下, __修饰的对象不会增加其引用计数,避免了循环引用
- ARC下,__block修饰的对象会被强引用,无法避免循环引用,要手动解环。
- __unsafe_unretained
- 修饰的对象不会增加其引用计数,避免了循环引用。
- 如果被修饰的对象在某以实际被释放,会产生悬垂指针。
*循环引用的示例
在平时开发中有没有遇到循环引用,你是怎么解决的。
- block的使用示例
- NSTimer的是示例
*NSTimer的训话引用问题
VC持有轮播器,要添加对象,对象和NStimer是互相强引用。
NSTimer会被Runloop强引用,所以弱引用没有用。
非重复的NSTimer中,Timer结束之后的回调中,invalid和置为nil
如果是重复的NSTimer,中间使用以个中间对象,中间对象对NStimer和对象弱引用,而NSTimer对中间对象强引用。
下次NStimer回来判断对象是否配释放了
- 内存管理总结
什么是ARC,VVLM编译器和Runtime协作管理?
为什么weak指针指向的对象在废弃之后会被置为nil?
苹果是什么实现AutoReleasePool的?
什么和怎么避免循环引用?