iOS面试-内存管理回答
操作系统主要分为两类存储: 1. 指令集储存 2. 数据存储
由于指令集存储主要由硬件的寄存器帮我完成,效率最高;我们在开发时主要关注的数聚存储;
iOS系统里从低到高数据存储分为5类: 代码区、常量区、全局/静态变量区(初始化过的一段区域、为初始化的一段区域)、堆区、栈区
由于除了堆之外,其他数据存储区域都是操作系统进行分配和回收,我们在开发过程中主要关注的是堆区的存储问题:
堆区的管理方式是引用计数管理: 每一个oc对象都有标记自己的引用计数,当有新指针指向它时,它的引用计数加一, 当指向它的指针被设为nill时,它的引用计数减一;当它的引用为0,就会系统销毁;
引用计数管理的思想是: 谁创建,谁释放。
引用计数管理分为两种情况:
MRC 手动管理方式: 在程序中显式的执行以下的指令:
当我们对应一个对象执行 alloc/new/copy/mutilCopy/就持有该对象的引用,或者执行retain,该对象的引用计数就会加一,当我们对一个执行release 时,该对象的引用计数就会减一;
ARC 自动管理方式: 程序在编译时,编译器会在适当的地方加入retain/release;
引用计数管理引进的问题:
- 内存泄漏: 当两个对象彼此持有对方,双方的引用计数都不可能为0 ,那么它们就永远不会被操作系统销毁,一致逗留在内存,造成了内存泄漏。
引用计数管理和java中的gc(垃圾回收机制有什么不同):
gc优点:
- 可以回收任何没有被持有的对象图谱,包括循环引用部分;
- gc程序运行在后台,可以定期的进行垃圾检查;(时间不定,可能是检测到存储不足或者上一次检测后的固定一段时间运行)
gc缺点: - 由于gc程序运行在后段,需要消耗一定cpu、内存资源,对耗电量也是有一定的影响,它运行时它的优先级应该最高的,可能会挂起一些app内的线程,略影响性能;
- 由于对象的检测、释放都在后台,释放时机不能确定;
引用计数优点:
- 可以实时及时的释放没有引用的对象;
- 没有后台运行,不会占用cpu、内存资源,不会影响app性能;
引用计数缺点:
- 不能处理缓存引用的问题;
常见的内存问题:
- 内存泄漏
内存泄漏原因: 是指动态分配的对象,使用完成后没有被曹彤系统进行回收造成。导致该对象一致逗留在内存,其他的代码又无法访问,这种现象为内存泄漏。
- 野指针
- 指针没有赋地址值 2. 指向的对象被操作系统提前释放,释放后未对指针变量设置为nil;这时使用指针时,它指向一块垃圾内存地址,保存 EXC_BAD_ACCESS
- 空指针
是指没有指向任何内容的指针。一般在对象销毁的时候,对指针变量赋值0来避免,对一个为0的空指针,不会报错,只是没有相应而已。
- 循环引用
彼此持有对方,操作系统无法根据规则释放它们。解决思路是一方不强持有对象即可,或者用完及时的销毁。
- 其他内存问题
5.1 NSNotification addObserver 之后,记得在 dealloc 里面添加 remove。
5.2 动画的 repeat count 无限大,而且也不主动停止动画,基本就等于无限循环了。
5.3 forwardingTargetForSelector 返回了 self。