美文网首页iosiOS 面试知识集合
(三)iOS 开发之内存管理

(三)iOS 开发之内存管理

作者: 神迹之风 | 来源:发表于2018-11-12 18:12 被阅读25次

内存管理是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 都是深拷贝。

相关文章

  • iOS 内存管理 部分三

    主要讲解日常开发中定时器的选择; iOS 内存管理 部分一iOS 内存管理 部分二iOS 内存管理 部分三i...

  • iOS性能调优之--内存管理

    iOS性能调优之--内存管理 iOS性能调优之--内存管理

  • iOS之从MRC到ARC内存管理详解

    概述 在iOS中开发中,我们或多或少都听说过内存管理。iOS的内存管理一般指的是OC对象的内存管理,因为OC对象分...

  • NSTaggedPointer和NONPOINTER_ISA

    内存管理之Tagged pointer iOS开发者对引用计数这个名词肯定不陌生,引用计数是苹果为了方便开发者管理...

  • iOS概念攻坚之路(三):内存管理

    前言 iOS 的内存管理不止是 「引用计数表」。 iOS 开发者基本都知道 iOS 是通过「引用计数」来管理内存的...

  • iOS 内存管理

    在开发中,内存管理是一个必要的技能,研究iOS 开发,我们通过内存布局、内存管理方案、数据结构、ARC/MRC、引...

  • iOS - 内存管理(三)之ARC

    前言 阅读本文前请先理解前面的两篇内容《iOS - 内存管理(一)之MRR》和 《iOS - 内存管理(二)之Co...

  • 浅谈iOS内存管理

    作为一个iOS开发者,了解iOS的内存管理是必不可少的。 iOS采取的内存管理策略 iOS没有垃圾回收机制,采用了...

  • iOS-归纳

    iOS内存分区,堆区 栈区等 内存管理 属性关键字、内存分区总结 iOS- 数据存储iOS开发数据库-FMDBiO...

  • iOS ARC下的内存管理

    ARC 能够解决 iOS 开发中 90% 的内存管理问题,但是另外还有 10% 内存管理,是需要开发者自己处理的,...

网友评论

    本文标题:(三)iOS 开发之内存管理

    本文链接:https://www.haomeiwen.com/subject/dricfqtx.html