IOS知识积累

内存管理

2021-06-23  本文已影响0人  叔简

内存布局

内存分区.png

内存管理方案

NONPOINTER_ISA

arm64结构下是64位

散列表方式

sideTables()结构

SIDETABLE

散列表方式.png

为什么不是一个SIDETABLE? 为什么要组成SIDETABLES呢?

怎么样实现快速分流?

SideTables的本质是一张Hash表。
可能有64个SideTable存储不同的引用计数表、和弱引用表

什么是hash算法

对象指针可以作为Key通过hash函数计算计算出hash表中你的value值的下标也就是索引。

hash查找的过程

给定值是对象内存地址,目标是数组下标索引。

给了一个对象的内存地址,通过哈希函数的运算,得到了一个集合的下标索引值

对象的内存地址指针 % 数组的count就可以得到这个数组中的索引

这样就查找速度快了

散列表方案设计的数据结构

引用计数表

实际上是一个refcountMap(hash表或者是字典),提高查找效率,存储查找都是hsah,找到

弱引用表

weak_table_t也是一张hash表,

MRC和ARC

MRC

手动引用计数,进行内存管理

ARC

自动引用计数

ARC和MRC的区别

引用计数管理

实现原理分析

alloc实现

retain实现

release实现

retainCount的实现

dealloc的实现

OBJECT_DISPOSE实现

OBJC_DESTRUCTINSTANCE的实现

CLEARDEALLOCCATING的实现

弱引用管理

弱引用调用栈

弱引用调用栈.png

当清除weak变量 通知设置指向为nil, 它是如何置nil的

如何将weak自动置为nil.png

完整过程

总结

自动释放池

自动释放池的面试题.png

编译器改写

objc_autoreleasepoolPush和objc_autoreleasePoolPop的函数调用栈

自动释放池的数据结构

ATUORELEASEPOOLPAGE的数据结构

AtuoreleasePoolPage::Push

AutoreleasePoolpagePush操作的原理.png

autorelease

autorelease的实现过程.png

AtuoreleasePoolPage::Pop

双向链表的概念

双向链表的结构.png

栈结构概念

栈结构.png

面试题自动释放池的实现结构是什么?

以栈为节点通过双向链表的形式组合而成

自动释放池的总结

下面代码什么时候释放

viewdidload{
    NSMutableArray *array = [NSSmutableArray array];
}

在当次runloop将要结束的时候调用AutoreleasePoolPage::Pop()

多次嵌套就是多次插入哨兵对象

关于autoreleasepool为和可以嵌套调用?

实际上多次嵌套插入哨兵对象,每次进行autoreleasePool的代码块创建的时候,假如autoreleasePoolpage没有满的情况下,系统就会在当前autoreleasePoolpage栈中进行一次哨兵对象的插入,如果满了会创建一个新的autoreleasePoolpage,然后当前的autoreleasePoolpage中的child指针指向新创建的autoreleasePoolpage。

所以autoreleasepool可以多层嵌套调用

循环引用

三种循环引用:

自循环引用

自循环引用.png

相互循环引用

相互循环引用.png

多循环引用(大环)

大环循环引用(多循环引用).png

如何破除循环引用?

具体解决方案:

__WEAK 破解循环引用

__weak避免产生循环引用.png

__BLOCK破解* 破解循环引用

__UNSAFE_UNRETAINED 破解循环引用

循环引用示例

在开发过程中,你遇到过哪些循环引用问题,你又是如何解决的?
有一个页面有一个banner滚动栏,每3秒滚到一次。一般有一个banner对象,VC对它强持有,
banner对象的需求是每3秒滚动一次。需要添加一个NSTimer,当我向banner对象添加回调的时候,NSTimer会对banner对象施加一个强引用,这个时候就产生了相互循环引用问题。

实际上,NSTimer创建完成以后会有一个主线程RunLoop去强引用NSTimer强引用。就算是VC退出释放掉,那么banner对象也不会释放,因为主线程runLoop强引用了这个对象。

NSTimer有重复,以及非重复定时器,假如是非重复定时器,那么在NSTimer回调完成以后设置无效并置nil,那么就破解了循环引用。

假如NSTimer重复多次回调

第一种:在NSTimer和Banner之间设置一个中间对象,这个中间对象分别弱引用NSTimer和banner对象。那么当VC释放掉,banner对象也就释放掉了,NSTimer的回调会去中间对象,而中间对象只要判断banner对象为不为nil 如果为nil就直接无效化NSTimer。
NSTimer的循环引用问题.png

考点

MST

如果我们对一个类添加了关联对象,那么在这个类被释放以后会清除掉这个关联对象吗?

会的,因为系统在dealloc中释放了关联对象

关于autoreleasepool为和可以嵌套调用?

实际上多次嵌套插入哨兵对象,每次进行autoreleasePool的代码块创建的时候,假如autoreleasePoolpage没有满的情况下,系统就会在当前autoreleasePoolpage栈中进行一次哨兵对象的插入,如果满了会创建一个新的autoreleasePoolpage,然后当前的autoreleasePoolpage中的child指针指向新创建的autoreleasePoolpage。

autoreleasePool的应用场景

在for循环中alloc图片数据等内存消耗较大的场景手动插入autoreleasePool。

autoreleasePool实现原理:

以栈为节点,通过双向链表的形式组合而成的数据结构

什么是ARC

ARC是由LLVM编译器以及runtime协作来为我们实现自动引用计数的管理

为什么weak指针指向的对象在废弃之后会被自动置为nil

当对象在被废弃之后,dealloc的内部方法实现当中会调用清除弱引用的方法,然后在清除弱引用的方法中会通过hash算法来查找被废弃对象在弱引用表当中的位置来提取它所对的人用引用指针的列表数组,然后进行for循环遍历,把每一个弱引用指针都置为nil

苹果是如何实现AutoreleasePool

AutoreleasePool是以栈为节点,双向链表形式来合成的数据结构。

什么是循环引用?你遇到过哪些循环引用,是怎么解决的?

上一篇下一篇

猜你喜欢

热点阅读