1.内存布局相关
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
2.3 散列表方式
2.4 为什么不是一个SideTable?
一个的话,为了保证线程安全,同时操作时候。会有效率问题。 多个的话,可以用分离锁方案。即分拆成多个,分别加锁,不同的话可以异步,同一个就要等待。
2.5 怎样实现快速分流? Side Tables的本质是一张Hash表。
通过Hash查找,提高效率。
3.数据结构相关
3.1 自旋锁 Spinlock_t Spinlock_t 是“忙等”的锁, 适用于轻量访问。
3.2引用计数表 RefcountMap
3.3 弱引用表 weak_table_t
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实现
object_dispose()实现
objc_destructInstance()实现
clearDeallocating()实现
6.弱引用管理相关
6.1 添加weak变量
6.2 清除weak变量,同时设置指向为nil
6.3 为什么weak指针指向的对象在废弃之后会被自动置为nil?
当对象被废弃之后,dealloc方法的内部实现当中会调用一个清除弱引用的方法,然后清除弱引用的时候,会通过哈希算法查找被废弃对象在弱引用表中的位置,来提取它所对应的弱引用指针的列表数组,然后for循环遍历,把每一个weak指针都置为nil。
7.自动释放池相关
8.循环引用相关
自循环引用、相互循环引用、多循环引用
8.1 如何破除循环引用?具体解决方案都有哪些?
避免产生循环引用、在合适的时机手动断环。
__weak 、 __block 、__unsafe_unretained
8.2 循环引用示例? 以NSTimer为示例,解决方法是:
通过创建一个中间对象,令中间对象持有两个弱引用变量,分别为NSTimer 和 原对象,然后在NSTimer中直接分派的回调在中间对象实现的,然后在中间对象实现的NSTimer回调方法当中,对他所持有的targer进行值的判断,如果说当前值存在,那么直接把NSTimer回调给原对象,如果当前对象已经被释放,那我们设置NSTimer为无效状态,就可以解除当前线程的Runloop对NSTimer、NSTimer对中间对象的强引用。