(三)iOS 开发之内存管理

内存管理是iOS开发中的重点和难点,也是技能进阶的重要关口,也常常在面试问题中出现。内存管理涉及到的核心话题包括:内存的管理规则、垃圾回收机制、内存泄漏和循环引用等等。下面整理了iOS中涉及到的内存管理相关知识。


(一)iOS 开发中的内存管理规则

引用计数

OC 中通过引用计数来实现内存管理:当一个对象被持有的时候计数加一,不再被持有的时候引用计数减一,当引用计数为零的时候,则将这个对象释放。

  • MRC:手动引用计数,iOS 5 之前的版本采用。
  • ARC:自动引用计数,iOS 5 以及之后的版本采用。
MRC 和 ARC 之间的转换
  • MRC 转 ARC :在控制开关中添加-fobjc-arc 以ARC进行编译。
  • ARC 转 MRC :在控制开关中添加-fno-objc-arc 以MRC进行编译。
自动释放池

OC对象的生命周期取决于引用计数,我们有两种方式可以释放对象:一种是直接调用release释放;另一种是调用autorelease将对象加入自动释放池中。自动释放池用于存放那些需要在稍后某个时刻释放的对象。

自动释放池中 release 和 drain 的区别

release 和 drain 的作用是一样的,都是清理自动释放池,区别是:drain 在支持 GC 的系统中(Mac)可以引起 GC 回收操作,而 release 不可以


(二)Objective-C 开发中的垃圾回收

垃圾回收(Garbage Collection, GC)简单地说就是程序中及时处理废弃不用的内存对象的机制,防止内存中废弃对象堆积过多造成内存泄漏。

平台局限性

Objective-C 语言本身是支持垃圾回收机制的,但是具有平台局限性,仅限于Mac 桌面系统开发中,在iPhone 和 iPad 等苹果移动端开发中是不支持垃圾回收机制的。

垃圾回收和引用计数的区别

垃圾回收是宏观的,对整体进行内存管理:将所有对象看作一个集合,然后在GC循环中定时监测活动对象和非活动对象,及时将永不倒的非活动对象释放以避免内存泄漏,也就是说将用不到的垃圾对象交给 GC 来管理释放,而无需开发者关心。
相比于 GC,引用计数是局部性的,是管理每个对象的引用计数,单个对象引用计数为0后会马上被释放。


(三)僵尸对象

产生原因

一个引用计数为0的Objective-C被释放后就变成僵尸对象,也就是过度释放的对象。

调试方法

遇到EXC_BAD_ACCESS 这类问题一般都是僵尸对象引起的,可以开启僵尸模式(Zombie Objects)定位。具体步骤这里不详细给出。


(四)野指针

产生原因

野指针又叫“悬挂指针”,野指针出现的原因是指针没有赋值,或者是指针指向的对象已经被释放掉了。开发中应该给野指针及时赋予零值,避免内存报错。
与空指针区别:向空指针发送消息不会报错。

调试方法

野指针指向一块随机的垃圾内存,向它们发送消息会报 EXC_BAD_ACCESS 错误导致程序崩溃。可以开启僵尸模式(Zombie Objects)定位。具体步骤这里不详细给出。


(五)空指针

定义

空指针不用于野指针,它是一个没有指向任何内容的指针。空指针是有效的指针,值为 nil、NULL、Nil 或者0等,给空指针发送信息不会报错,只是不会相应信息而已。


(六)nil、Nil、NULL 和 [NSNull null] 的区别

  • nil:当一个对象置为nil时,这个对象的内存地址就会被系统收回。置空之后是不能进行retain,copy等跟引用计数有关的任何操作的。
  • Nil:nil完全等同于Nil,只不过由于编程习惯,人们一般把对象置空用nil,把类置空用Nil。
  • NULL :这个是从C语言继承来的,就是一个简单的空指针。
  • [NSNull null]:[NSNull null]和nil的区别在于,nil是一个空对象,已经完全从内存中消失了,而如果我们想表达“我们需要有这样一个容器,但这个容器里什么也没有”的观念时,我们就用到[NSNull null],它就是为“值为空的对象”。如果你查阅开发文档你会发现NSNull这个类是继承NSObject,并且只有一个“+ (NSNull *) null;”类方法。这就说明NSNull对象拥有一个有效的内存地址,所以在程序中对它的任何引用都是不会导致程序崩溃的。

(七)内存泄漏

产生原因

内存泄漏指动态分配内存的对象在使用完后没有被系统回收,导致对象始终占用内存,又无法通过代码访问。大量内存泄漏会导致系统内存不足的问题。

解决与调试方法
  • 对程序员而言,要深入理解内存管理原则,养成良好的编程习惯以减少内存泄漏情况的发生。
  • 使用 Xcode 提供的检测调试工具 Instruments,检测可能导致内存泄漏的代码,并及时优化。

(八)循环引用

产生原因

当多个对象相互持有形成一个封闭的环时,循环引用问题随之出现,导致内存泄漏。

解决方法
  • 自己明确知道这里会存在循环引用,在合理的位置主动断开环中的一个引用(置为nil),使得对象得以回收;
  • 使用弱引用。
iOS 开发中常出现循环引用的地方

(九)深拷贝和浅拷贝

浅拷贝只是复制了内存地址,也就是对内存空间的引用;深拷贝是开辟新的空间并且复制原空间相同的内容,新指针指向新空间内容。
对 immutable 对象进行 copy 操作,是浅拷贝,mutableCopy 操作是深拷贝;对 mutable 对象进行 copy 和 mutableCopy 都是深拷贝。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 软件运行时会分配和使用设备的内存资源,因此,在软件开发的过程中,需要进行内存管理,以保证高效、快速的分配内存,并且...
    maTianHong阅读 4,005评论 0 0
  • 内存管理ARC处理原理ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只...
    阳明AI阅读 2,812评论 0 3
  • 我说各位点单的看官~鹿石咖啡的热点资讯和原创内容会越来越丰富,大家稍安勿躁,你们点的看单我们都会照顾到。这次说些让...
    鹿石咖啡阅读 2,383评论 0 0
  • 文:凌言 01 沈冰在手机上编辑着信息,编辑好了自己又看了一遍:刘超,我们以后不要再联系了!你也知道,这段时间,你...
    凌言随语阅读 3,379评论 0 0
  • 寒冷掩盖不了春天的本色 寒冷过后 春意更浓 阴霾掩盖不了天空的本色 阴霾过后 蓝天更蓝 苦难掩盖不了坚毅的本色 苦...
    千尹阅读 6,791评论 49 72