iOS平台内存使用原则

2 iOS平台内存使用原则

2.1 对象的所有权与销毁

2.1.1 谁创建,谁释放;

如果是以alloc,new或者copy,mutableCopy创建的对象,则必须调用release或者autorelease方法释放内存;

如果没有释放,则导致内存泄漏!

2.1.2 谁retain,谁释放;

如果对一个对象发送 retain消息,其引用计数会+1,则使用完必须发送release或者autorelease方法释放内存或恢复引用计数;

如果没有释放,则导致内存泄漏!

2.1.3 没创建且没retain,别释放;

不要释放那些不是自己alloc或者retain的对象,否则程序会crash

不要释放autorelease的对象,否则程序会crash

2.2 对象的深拷贝与浅拷贝

一 般来说,复制一个对象包括创建一个新的实例,并以原始对象中的值初始化这个新的实例。复制非指针型实例变量的值很简单,比如布尔,整数和浮点数。复制指 针型实例变量有两种方法。一种方法称为浅拷贝,即将原始对象的指针值复制到副本中。因此,原始对象和副本共享引用数据。另一种方法称为深拷贝,即复制指针 所引用的数据,并将其赋给副本的实例变量。

2.2.1 深拷贝

深拷贝的流程是 先创建一个的对象且引用计数为1,并用旧对象的值初始化这个新对象;

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA copy];

objB是一个新对象,引用计数为1,且objB的数据等同objA的数据;

注意: objB需要释放,否则会引起内存泄漏!

2.2.2 浅拷贝

浅拷贝的流程是,无需引入新的对象,把原有对象的引用计数+1即可

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA retain];

注意: objB需要释放,恢复objA的引用计数,否则会引起内存泄漏!

2.3对象的存取方法

2.3.1 属性声明和实现

变量声明的常用属性类型包括readonly,assign,retain和copy;且系统会自动为声明了属性的变量生成set和get函数;

readonly属性: 只能读,不能写;

assign属性: 是默认属性,直接赋值,没有任何保留与释放问题;

retain属性: 会增加原有对象的引用计数并且在赋值前会释放原有对象,然后在进行赋值;

copy属性:  会复制原有对象,并在赋值前释放原有对象,然后在进行赋值;

2.3.2 使用属性声明可能带来的隐患

当一个非指针变量使用retain(或者copy)这个属性时,尽量不要显性的release这个变量;直接给这个变量置空即可;否则容易产生过度释放,导致程序crash;例如:

ClassA类的strName是NSString* 类型的变量且声明的属性为retain;

ClassA.strName = nil;  /* 释放原有对象且对此对象赋值为空 */

[ClassA.strName release]; /* strName内存可能已经被释放过了,将导致程序crash */

Assign这个属性一般是非指针变量(布尔类型,整形等)时用这个类型;属于直接赋值型,不需要考虑内存的保留与释放;

如果一个指针类型的变量使用assign类型的属性,有可能引用已经释放的变量;导致程序crash; 例如:

ClassB* obj =[[[ClassB alloc] init] autorelease];

……

ClassA.strName = obj; /* strName 指向obj的内存地址*/

后续在使用ClassA.strName的时候, 因为obj是autorelease的,可能obj的内存已经被回收;导致引用无效内存,程序crash;

3iOS平台AutoRelease机制

3.1 自动释放池的常见问题

大家在开发iOS程序的时候,是否遇到过在列表滑动的情况内存莫名的增长,频繁访问图片的时候内存莫名的增长,频繁的打开和关闭数据库的时候内存莫名的增长……这些都是拜iOS的autorelease机制所赐;具体分析如下:

1: 滑动列表的时候,内存出现莫名的增长,原因可能有如下可能:

1:没有使用UITableView的reuse机制; 导致每显示一个cell都用autorelease的方式重新alloc一次;导致cell的内存不断的增加;

2:每个cell会显示一个单独的UIView, 在UIView发生内存泄漏,导致cell的内存不断增长;

2: 频繁访问图片的时候,内存莫名的增长;

频繁的访问网络图片,导致iOS内部API,会不断的分配autorelease方式的buffer来处理图片的解码与显示; 利用图片cache可以缓解一下此问题;

3: 频繁打开和关闭SQLite,导致内存不断的增长;

在进行SQLite频繁打开和关闭操作,而且读写的数据buffer较大,那么SQLite在每次打开与关闭的时候,都会利用autorelease的方式分配51K的内存; 如果访问次数很多,内存马上就会顶到几十兆,甚至上百兆! 所以针对频繁的读写数据库且数据buffer较大的情况, 可以设置SQLite的长连接方式;避免频繁的打开和关闭数据库;

3.2 自动释放池的概念

NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声名为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。

ClassA *obj1 = [[[ClassA alloc] init]autorelease]; //retain count = 1,把此对象加入autorelease pool中

NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄露。

3.3 自动释放池的作用域与嵌套

AutoreleasePool是可以嵌套使用的!
池是被嵌套的,嵌套的结果是个栈,同一线程只有当前栈顶pool实例是可用的:

当短生命周期内,比如一个循环中,会产生大量的临时内存,可以创建一个临时的autorelease pool,这样可以达到快速回收内存的目的;

3.4 自动施放池的手动创建与自动创建

3.4.1 需要手动创建自动释放池

●如果你正在编写一个不是基于Application Kit的程序,比如命令行工具,则没有对自动释放池的内置支持;你必须自己创建它们。

●如果你生成了一个从属线程,则一旦该线程开始执行,你必须立即创建你自己的自动释放池;否则,你将会泄漏对象。

●如果你编写了一个循环,其中创建了许多临时对象,你可以在循环内部创建一个自动释放池,以便在下次迭代之前销毁这些对象。这可以帮助减少应用程序的最大内存占用量。

3.4.2 系统自动创建自动释放池

Application Kit会在一个事件周期(或事件循环迭代)的开端—比如鼠标按下事件—自动创建一个自动释放池,并且在事件周期的结尾释放它.

4 iOS平台内存使用陷阱

4.1 重复释放

在前文已经提到,不要释放不是自己创建的对象;

释放自己的autorelease对象,app会crash;

释放系统的autorelease对象,app会crash;

4.2 循环引用

循环引用,容易产生野引用,内存无法回收,最终导致内存泄漏!可以通过弱引用的方式来打破循环引用链;所谓的弱引用就是不需要retain,直接赋值的方式,这样的话,可以避免循环引用的问题,但是需要注意的是,避免重复释放的问题;

5 iOS平台内存报警机制

由于iOS平台的内存管理机制,不支持虚拟内存,所以在内存不足的情况,不会去Ram上创建虚拟内存;所以一旦出现内存不足的情况,iOS平台会通知所有已经运行的app,不论是前台app还是后台挂起的app,都会收到 memory warning的notice;一旦app收到memory warning的notice,就应该回收占用内存较大的变量;

5.1 内存报警处理流程

1: app收到系统发过来的memory warning的notice;

2: app释放占用较大的内存;

3: 系统回收此app所创建的autorelease的对象;

4: app返回到已经打开的页面时,系统重新调用viewdidload方法,view重新加载页面数据;重新显示;

5.2 内存报警测试方法

在Simulate上可以模拟低内存报警消息;

iOS模拟器 -> 硬件 -> 模拟内存警告;

开发者可以在模拟器上来模拟手机上的低内存报警情况,可以避免由于低内存报警引出的app的莫名crash问题;

6 iOS平台内存检查工具

6.1 编译和分析工具Analyze

iOS的分析工具可以发现编译中的warning,内存泄漏隐患,甚至还可以检查出logic上的问题;所以在自测阶段一定要解决Analyze发现的问题,可以避免出现严重的bug;

内存泄漏隐患提示

Potential Leak of an object allocated online ……

数据赋值隐患提示

The left operand of …… is a garbage value;

对象引用隐患提示

Reference-Counted object is used after itis released;

时间: 2024-11-24 19:01:21

iOS平台内存使用原则的相关文章

说说iOS与内存管理(上)

http://www.cocoachina.com/ios/20150625/12234.html 说起内存管理,看似老生常谈,而真正掌握内存管理的核心其实并不简单.ARC/MRR以及“谁分配谁就负责释放”这种基本原则是很重要的,但不是本文要讨论的重点.之前本人还没在小站发过相关的文章,本篇文章中,我本人是想结合实际开发和调试中遇到的一些细节问题,来谈谈iOS的内存管理内在机制和调试方法. 上一篇文章已经是4月份的了,时间飞快又过去了好久,小站5月份没有文章更新,罪过罪过.最近小站的站长我又转换

经典好文:android和iOS平台的崩溃捕获和收集

通过崩溃捕获和收集,可以收集到已发布应用(游戏)的异常,以便开发人员发现和修改bug,对于提高软件质量有着极大的帮助.本文介绍了iOS和android平台下崩溃捕获和收集的原理及步骤,不过如果是个人开发应用或者没有特殊限制的话,就不用往下看了,直接把友盟sdk(一个统计分析sdk)加入到工程中就万事大吉了,其中的错误日志功能完全能够满足需求,而且不需要额外准备接收服务器. 但是如果你对其原理更感兴趣,或者像我一样必须要兼容公司现有的bug收集系统,那么下面的东西就值得一看了. 要实现崩溃捕获和收

【转】iOS平台的应用程序调试与分析

转自:看雪学院的文章 iOS平台的应用程序调试与分析 作者:zhuliang转载请保证文章完整并注明来自看雪或cd-team 本文阐述如何在iOS平台上对应用程序进行调试与分析,旨在指导新手分析iOS程序,高手请无视.内容包括软件硬件的准备.代码的解密.符号信息的获取.用gdb调试等,最后以京东LeBook为例子进行演示.1.为什么要进行调试与分析研究iOS程序有很多用处,比如:找bug或者漏洞,想知道某程序有没有漏洞或者bug.某程序能实现某功能,我想知道如何实现,如ios6发短信功能,还有比

理解 iOS 的内存管理

理解 iOS 的内存管理 远古时代的故事 那些经历过手工管理内存(MRC)时代的人们,一定对 iOS 开发中的内存管理记忆犹新.那个时候大约是 2010 年,国内 iOS 开发刚刚兴起,tinyfool 大叔的大名已经如雷贯耳,而我还是一个默默无闻的刚毕业的小子.那个时候的 iOS 开发过程是这样的: 我们先写好一段 iOS 的代码,然后屏住呼吸,开始运行它,不出所料,它崩溃了.在 MRC 时代,即使是最牛逼的 iOS 开发者,也不能保证一次性就写出完美的内存管理代码.于是,我们开始一步一步调试

android和iOS平台的崩溃捕获和收集

转自:http://www.cnblogs.com/lancidie/archive/2013/04/13/3019349.html 通过崩溃捕获和收集,可以收集到已发布应用(游戏)的异常,以便开发人员发现和修改bug,对于提高软件质量有着极大的帮助.本文介绍了iOS和android平台下崩溃捕获和收集的原理及步骤,不过如果是个人开发应用或者没有特殊限制的话,就不用往下看了,直接把友盟sdk(一个统计分析sdk)加入到工程中就万事大吉了,其中的错误日志功能完全能够满足需求,而且不需要额外准备接收

iOS平台上音频编码成aac

小程之前介绍解码aac时,曾经使用了fadd,并且有提到,如果想编码成aac格式,可以使用facc.fdk-aac等,但使用fdk-aac等编码方式,都是软编码,在cpu的消耗上会明显大于硬件编码. 硬编码的优势是可以用硬件芯片集成的功能,高速且低功耗地完成编码任务. 在iOS平台,也提供了硬编码的能力,APP开发时只需要调用相应的SDK接口就可以了. 这个SDK接口就是AudioConverter. 本文介绍iOS平台上,如何调用AudioConverter来完成aac的硬编码. 从名字来看,

IOS平台APP安全Checklist

#1. 前言IOS平台APP安全风险相关的一般性Checklist,保障IOS客户端安全评估的质量与效率.#2. 数据安全##2.1 传输安全该类漏洞的审查场景:APP通过网络发送或接收敏感信息,比如用户口令.用户隐私信息等,或者通过网络下发的数据执行某些敏感操作**漏洞类型说明:**由于移动设备通常是通过wifi上网,因而面临网络窃听.网络劫持等中间人攻击行为,因此对于敏感信息需要加密传输,并且对接收到的重要数据也需要进行完整性校验.如果APP自身实现了加密及完整性校验的机制,需要确认机制是否

没有苹果电脑打包iOS平台的 Ionic 2程序——《Ionic 2 实例开发》更新内容

没有苹果电脑打包iOS平台的 Ionic 2程序--<Ionic 2 实例开发>更新内容春节刚过,祝各位新的一年里万事如意,一帆风顺.<Ionic 2 实例开发>在这段时间里更新了如下内容:Ionic 2 中使用管道处理数据Ionic 2 中使用HTTP与远程服务器交互数据Ionic 2 中的样式与主题没有苹果电脑打包iOS平台的 Ionic 2程序欢迎阅读.

在iOS平台使用ffmpeg解码h264视频流

来源:http://www.aichengxu.com/view/37145 在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,ffmpeg提供avformat_open_input接口,直接将文件路径或URL传入即可打开.读取视频数据.解码器初始参数设置等,都可以通过调用API来完成. 但是对于h264流,没有任何封装格式,也就无法使用libavformat.所以许多工作需要自己手工完成. 这里的h264流指AnnexB,也