iOS面试题(四)--内存管理相关

138 阅读3分钟

1.内存布局相关

image.png stack:方法调用

heap:通过alloc等分配的对象

bss:未初始化的全局变量等

data:已初始化的全局变量等

text:程序代码

2.内存管理方案相关

2.1 iOS操作系统是怎么进行内存管理的?

内存管理方案包括:

①TaggedPointer:针对小对象,如NSNumber、NSData类型等小对象的方案

②NONPOINTER_ISA:非指针型isa,存储引用技术是在64位架构下使用的一种方案,高效利用64位架构下isa指针的剩余内存空间

③散列表:在32位架构下使用以及64位架构下isa指针存放不下的场景下使用 也就是我们常说的引用计数表

2.2 NONPOINTER_ISA

image.png

image.png

2.3 散列表方式

image.png

image.png

2.4 为什么不是一个SideTable?

一个的话,为了保证线程安全,同时操作时候。会有效率问题。 多个的话,可以用分离锁方案。即分拆成多个,分别加锁,不同的话可以异步,同一个就要等待。

2.5 怎样实现快速分流? Side Tables的本质是一张Hash表。

image.png 通过Hash查找,提高效率。

image.png

3.数据结构相关

3.1 自旋锁 Spinlock_t Spinlock_t 是“忙等”的锁, 适用于轻量访问。

3.2引用计数表 RefcountMap

image.png

image.png

3.3 弱引用表 weak_table_t image.png

4.MRC&ARC相关

4.1 MRC 手动引用计数

alloc retain release retainCount autorelease dealloc

4.2 ARC 自动引用计数

ARC 是 LLVM 和Runtime协作的结果,ARC 中禁止手动调用retain/release/retainCount/autorelease/dealloc

ARC中新增weak、strong属性关键字

4.3 苹果是如何实现AutoreleasePool的?

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

5.引用计数管理相关

5.1 alloc实现

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

5.2 retain实现

SideTable& table = SideTables()[this];

size_t& refcntStorage = table.refcnts[this];

refcntStorage += SIDE_TABLE_RC_ONE;

5.3 release实现

SideTable& table = SideTables()[this];

RefcountMap::iterator it = table.refcnts.find(this);

it -> second -= SIDE_TABLE_RC_ONE;

5.4 retainCount实现

SideTable& table = SideTables()[this];

size_t refcnt_result = 1;

RefcountMap::iterator it = table.refcnts.find(this);

refcnt_result += it ->second >> SIDE_TABLE_RC_SHIFT;

5.5 dealloc实现 image.png

object_dispose()实现 image.png

objc_destructInstance()实现 image.png

clearDeallocating()实现 image.png

6.弱引用管理相关

6.1 添加weak变量 image.png

6.2 清除weak变量,同时设置指向为nil image.png

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

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

7.自动释放池相关

image.png

8.循环引用相关

自循环引用、相互循环引用、多循环引用

8.1 如何破除循环引用?具体解决方案都有哪些?

避免产生循环引用、在合适的时机手动断环。

__weak 、 __block 、__unsafe_unretained

image.png

image.png

image.png

8.2 循环引用示例? 以NSTimer为示例,解决方法是:

image.png 通过创建一个中间对象,令中间对象持有两个弱引用变量,分别为NSTimer 和 原对象,然后在NSTimer中直接分派的回调在中间对象实现的,然后在中间对象实现的NSTimer回调方法当中,对他所持有的targer进行值的判断,如果说当前值存在,那么直接把NSTimer回调给原对象,如果当前对象已经被释放,那我们设置NSTimer为无效状态,就可以解除当前线程的Runloop对NSTimer、NSTimer对中间对象的强引用。