iOS面试之内存管理

2021-03-25  本文已影响0人  iOS王的男人

原文地址https://www.jishudog.com/8744/html

推荐👇:

推荐作者:iOS的火影乱斗

地址

内存布局


iOS程序下内存布局

不同内存布局区域的含义
stack(栈):方法调用
heap(堆):通过alloc等分配的对象
bss:未初始化的全局变量
data:已初始化的全局变量
text:程序代码

内存管理方案

散列表

散列表中数据结构

ARC&&MRC

  1. MRC 手动引用计数
    • alloc
    • retain
    • release
    • retainCount
    • autorelease
    • dealloc

2.ARC 自动引用计数

引用计数

[图片上传失败...(image-584a89-1608785619322)]

object_dospose()函数内部实现分析


clearDeallocating()内部实现

弱引用


weak变量的添加过程

如何添加weak变量的?
对象指针在经过编译器的编译之后调用objc_initweak(),然后storeweak()方法,经过一系列的函数调用,最终在weak_register_no_lock()进行弱引用变量的添加,通过hash算法位置查找,如果已经存在当前对象对应的弱引用数组,则直接加进去,如果没有则创建新个新的弱引用数组,存放新的weak指针


系统如何实现将废弃的weak指针置为nil

系统如何实现将废弃的weak指针置为nil?
当对象被dealloc后废弃之后,会调用弱引用清除的相关函数。然后在函数实现中,根据当前对象指针,查找弱引用表,把当前对象对应的弱引用都拿出来,然后遍历所有的弱引用指针置为nil

自动释放池

AutoreleasePool的实现原理是怎么样的?

AutoreleasePool是以栈为结点,通过双向链表的形式组合而成的数据结构。编译器会将@autoreleasepool{}改写,如下 图。实际objc_autoreleasePoolPop函数在内部做了pop操作,批量将autoreleasepool中的所有的对象都会做一次release操作


编译器改写@autoreleasepool{}

下面对上面的主要函数进行一个简单的说明

AutoreleasePool的结构

什么是双向链表?


双向 链表结构

[obj autorelease]的实现(对象加入自动释放池)

先判断当前next指针是否指向栈顶,如果不是直接加入;如果是,则增加一个栈结点到链表上,在新的栈添加对象;移动next指针

AutoreleasePoolPage::push实现流程(释放池多层嵌套)
AutoreleasePoolPage::pop实现流程(与push相反)
AutoreleasePool为何可以嵌套使用?

多次插入哨兵对象,也就是对一个新的releasePool的创建,如果当前栈没有满,则不需要创建新的page,如果满了,新增一个栈节点

下面这个图中,array对象在什么时候释放呢?

答:在档次runloop将要结束的时候调用AutoreleasePoolPage:pop(),对array对象执行release操作

AutoreleasePool的使用场景?

在for循环中,alloc图片数据等内存消耗较大的场景手动插入autoreleasePool,每一次for循环都进行一次内存的释放,降低内存消耗

循环引用


自循环引用 对自身强持有



相互循环引用



多循环引用
常见的循环引用以及破除方法:
如何破除循环引用?
具体解决方案有哪些?
__block在ARC和MRC条件下的区别
__unsafe_unretained破解
循环引用的示例?(平时开发时是否有遇到循环引用,又是怎么解决的?)
  1. Block使用示例(在后面block讲解时)
  2. NSTimerd的循环引用问题

文章到这里就结束了,你也可以私信我及时获取面试资料。如果你有什么意见和建议欢迎给我留言。

上一篇下一篇

猜你喜欢

热点阅读