




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】iOS内存暴增问题追查与使用陷阱
iOS平台的内存使用引用计数的机制,并且引入了半自动释放机制;这种使用上的多样性,导致开发者在内存使用上非常容易出现内存泄漏和内存莫名的增长情况;本文会介绍iOS平台的内存使用原则与使用陷阱;深度剖析autorelease机制;低内存报警后的处理流程;并结合自身实例介绍内存暴增的问题追查记录以及相关工具的使用情况;TAG内存暴增,内存泄漏,autorelease;内存报警;
作为iOS平台的开发者,是否曾经为内存问题而苦恼过?内存莫名的持续增长,程序莫名的crash,难以发现的内存泄漏,这些都是iOS平台内存相关的常见问题;本文将会详细介绍iOS平台的内存管理机制,autorelease机制和内存的使用陷阱,这些将会解决iOS平台内存上的大部分问题,提高了程序的稳定性;iOS平台的内存管理采用引用计数的机制;当创建一个对象时使用alloc或者allWithZone方法时,引用计数就会+1;当释放对象使用release方法时,引用计数就是-1;这就意味着每一个对象都会跟踪有多少其他对象引用它,一旦引用计数为0,该对象的内存就会被释放掉;另外,iOS也提供了一种延时释放的机制AutoRelease,以这种方式申请的内存,开发者无需手动释放,系统会在某一时机释放该内存;由于iOS平台的这种内存管理的多样性,导致开发者在内存使用上很容易出现内存泄漏或者程序莫名崩溃的情况,本文会详细介绍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=[[ClassAalloc]init];ClassA*objB=[objA
copy];objB是一个新对象,引用计数为1,且objB的数据等同objA的数据;注意:
objB需要释放,否则会引起内存泄漏!2.2.2浅拷贝浅拷贝的流程是,无需引入新的对象,把原有对象的引用计数+1即可ClassA*objA=[[ClassAalloc]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.strNamerelease];Assign这个属性一般是非指针变量(布尔类型,×××等)时用这个类型;属于直接赋值型,不需要考虑内存的保留与释放;如果一个指针类型的变量使用assign类型的属性,有可能引用已经释放的变量;导致程序crash;例如:ClassB*obj=[[[ClassBalloc]init]
autorelease];……ClassA.strName=obj;后续在使用ClassA.strName的时候,因为obj是autorelease的,可能obj的内存已经被回收;导致引用无效内存,程序crash;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=[[[ClassAalloc]init]autorelease];//retaincount=1,把此对象加入autoreleasepool中NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retaincount为1,那么release之后,retaincount为0,对象正式被销毁。如果此时数组中成员的retaincount大于1,那么release之后,retaincount大于0,此对象依然没有被销毁,内存泄露。3.3自动释放池的作用域与嵌套AutoreleasePool是可以嵌套使用的!
池是被嵌套的,嵌套的结果是个栈,同一线程只有当前栈顶pool实例是可用的:当短生命周期内,比如一个循环中,会产生大量的临时内存,可以创建一个临时的autoreleasepool,这样可以达到快速回收内存的目的;3.4自动施放池的手动创建与自动创建3.4.1需要手动创建自动释放池●如果你正在编写一个不是基于ApplicationKit的程序,比如命令行工具,则没有对自动释放池的内置支持;你必须自己创建它们。●如果你生成了一个从属线程,则一旦该线程开始执行,你必须立即创建你自己的自动释放池;否则,你将会泄漏对象。●如果你编写了一个循环,其中创建了许多临时对象,你可以在循环内部创建一个自动释放池,以便在下次迭代之前销毁这些对象。这可以帮助减少应用程序的最大内存占用量。3.4.2系统自动创建自动释放池ApplicationKit会在一个事件周期(或事件循环迭代)的开端—比如鼠标按下事件—自动创建一个自动释放池,并且在事件周期的结尾释放它.4.1重复释放在前文已经提到,不要释放不是自己创建的对象;释放自己的autorelease对象,app会crash;释放系统的autorelease对象,app会crash;4.2循环引用
循环引用,容易产生野引用,内存无法回收,最终导致内存泄漏!可以通过弱引用的方式来打破循环引用链;所谓的弱引用就是不需要retain,直接赋值的方式,这样的话,可以避免循环引用的问题,但是需要注意的是,避免重复释放的问题;由于iOS平台的内存管理机制,不支持虚拟内存,所以在内存不足的情况,不会去Ram上创建虚拟内存;所以一旦出现内存不足的情况,iOS平台会通知所有已经运行的app,不论是前台app还是后台挂起的app,都会收到memorywarning的notice;一旦app收到memorywarning的notice,就应该回收占用内存较大的变量;5.1内存报警处理流程1:app收到系统发过来的memorywarning的notice;2:app释放占用较大的内存;3:系统回收此app所创建的autorelease的对象;4:app返回到已经打开的页面时,系统重新调用viewdidload方法,view重新加载页面数据;重新显示;5.2内存报警测试方法在Simulate上可以模拟低内存报警消息;iOS模拟器->硬件->模拟内存警告;开发者可以在模拟器上来模拟手机上的低内存报警情况,可以避免由于低内存报警引出的app的莫名crash问题;6.1编译和分析工具AnalyzeiOS的分析工具可以发现编译中的warning,内存泄漏隐患,甚至还可以检查出logic上的问题;所以在自测阶段一定要解决Analyze发现的问题,可以避免出现严重的bug;内存泄漏隐患提示:PotentialLeakofanobjectallocatedonline……数据赋值隐患提示:Theleftoperandof……isagarbagevalue;对象引用隐患提示:Reference-Countedobjectisusedafteritisreleased;
以上提示均比较严重,可能会引起严重问题,需要开发者密切关注!6.2内存检测工具6.2.1内存泄漏检测工具—LeakLeak工具可以很容易的统计所有内存泄漏的点,而且还可以显示在那个文件,哪行代码有内存泄漏,这样定位问题比较容易,也比较方面;但是Leak在统计内存泄漏的时候会把autorelease方式的内存也统计进来;所以我们在查找内存泄漏情况的时候,可以autorelease的情况忽略掉;Leak工具:
通过Leak工具可以很快发现代码中的内存泄漏,通过工具也可以很快找到发生内存泄漏的代码段:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年啸亭杂录题目及答案
- 建设工程质量保证方案
- 城乡供水水质在线监测方案
- 2025年生活垃圾试题及答案
- 财务咨询服务合作协议
- 2025南通中考数学试卷及答案
- 营业用房租赁合同
- 劳务派遣合同模板模板
- 护理考试试题及答案
- 会计电算化考试试题及答案
- 2025年巨量引擎医药健康行业营销白皮书
- 药物分析员理论知识考核试卷及答案
- 体验单元 《分类与打包》课件 2025-2026学年大象版科学二年级上册
- QC/T 262-2025汽车渗碳齿轮金相检验
- 2025年交通安全问答试题及答案
- 电子厂安全考试题库及答案大全
- 种植牙术后注意事项
- 2025下半年网络管理员考题试卷及答案
- 老年患者视听障碍的护理
- 《机械基础(第二版)》中职全套教学课件
- 部编人教版六年级道德与法治上册全册教学课件
评论
0/150
提交评论