内存管理

2020-07-23  本文已影响0人  Oh丶Really

一、内存布局

image
* stack 方法调用
* heap 通过alloc分配的对象
* bss 未初始化的全局变量等
* data 已初始化的全局变量等
* text 程序代码

二、内存管理方案

三、数据结构

1. NONPOINTER_ISA

image

2. 散列表

SideTables()结构 -- 实际为一个哈希表


image

SideTable结构


image
问题:为什么SideTable是好几张表,而不是一张表:

假如是一张表的话,系统的所有对象都会在一张表中,那么当对其进行操作的时候,那么必然需要加锁,当有大量相似操作的时候,效率会大大降低;多张表相当于多线程操作,可以提高效率

问题:怎样实现快速分流(怎样根据key找到SideTable位置):

SideTables本质是一张Hash表,通过哈希查找找到下表


image

例如:给定值是对象的内存地址,目标值是数组下标索引


image
不会遍历所有的表,所以会提高查找效率。

3.散列表的数据结构

自旋锁
引用计数表
image
size_t
image

实际是一个无符号的long型的值;第一位是是否有弱引用;第二位是是否有dealloc;其它位是引用计数位,所以在计算引用计数位的时候,需要向右偏移两位;

弱引用表
image

四、MRC、ARC

MRC

手动引用计数进行对象的内存管理


image

其中标红的是MRC特有的方法

ARC

五、引用计数管理

实现原理分析

1、alloc实现

经过一系列的调用,最终调用了C函数 calloc;
此时并没有设置引用计数位1;

2、retain实现

image

3、release实现

image

4、retainCount实现

image
问题:新alloc的对象为什么引用计数为1?
解答:因为,新alloc出来的对象,在引用计数表中是没有数值的,所以上面 it->second 读出的值为0,又声明的局部变量为1,所以相加之后 retainCount 为1.

5、dealloc实现

image

object_dispse()的实现:


image

objc_destructInstance() (销毁实例对象)的实现:


image
clearDeallocating() 的实现;
image

六、弱引用管理

image

1、添加 weak 变量:

image
一个 __weak 修饰的对象,系统会调用objc_initWeak()方法对其处理,最终会调用 weak_register_no_lock()方法对其进行具体操作,通过弱引用对象进行一个哈希运算查找到在对应弱引用表的位置,若此位置有弱引用数组则添加新的对象到数组中,若没有则重新创建弱引用地址,在第0个位置添加新的weak指针,后面的初始化为0或者nil

源码解析:


image image image image image image

2、清除weak变量,同时设置指向为nil的过程:

image

源码解析


image image image
当一个对象进行dealloc操作,系统会调用 weak_clear_no_lock() 方法对其操作,具体是系统会通过哈希算法查找对应的弱引用表中的位置,若找到则返回一个数组,数组中存储所有的弱引用关系表,然后系统对数组进行遍历,把所有的弱引用指针分别指向nil

七、自动释放出

问题:

image

1、AutoreleasePool

编译器会将@autoreleasepool{} 改写为


image

objc_autoreleasePoolPush:

image

objc_autoreleasePoolPop:

image
一次pop操作相当于一次批量的pop操作

2、AutoreleasePool的数据结构

双向链表
image

后入先出


image
AutoreleasePoolPage
image

原本的内存图:


image

发生push操作后:


image
[obj autorelease]的系统实现过程:
image

AutoreleasePoolPage::pop

自动释放池总结

八、循环引用

三种循环引用:

1、自循环引用

image

2、相互循环引用

image

3、多循环引用

image

注意点:

如何破除循环引用?

具体解决方案

1、__weak 破解

image

2、__block 破解

注意:

3、__unsafe_unretained 破解

NSTimer 的循环引用问题

1、若非循环 timer

可将 timer 设置无效,然后置空

2、循环 timer

设置中间对象,中间对象持有对 timer 和 VC 的弱引用变量。NSTimer 分派的回调是在中间变量中实现。在中间变量回调的方法中对其所持有的 target 进行判断,若当前值存在则将NSTimer的值回调给原对象;若不存在(已经被释放),则设置timer为无效状态,具体代码实现如下:


image

(修改系统方法实现)


image
(完成改写)
image

总结

上一篇 下一篇

猜你喜欢

热点阅读