利用leaks模板分析app的内存泄露

虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在。所以了解原理很重要。

这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置的使用。

本文假设你已经比较熟悉Obj-C的内存管理机制。

实验的开发环境:XCode 4.5.2

1、运行Demo。

先下载一个实现准备好的内存泄露的Demo吧:leak app

下载下来,打开运行,程序是一个寿司的列表,列出各种寿司卷。试着选择里面的几行,应该是选第二行的时候就崩溃了。崩溃截图:

在崩溃的地方断住了,知道crash的地方了,但是不知道具体crash的原因。

2、设置NSZombieEnabled


这是一个 “EXC_BAD_ACCESS”错误。我们打开XCode的选项:“NSZombieEnabled”
。在crash时可能会给你更多的一些提示信息。

设置步骤:1

2:勾上红色框里的

运行,按刚才的操作选中其中的cell。再次crash,这次在output窗口会看到多了一项错误信息:

2012-11-28 13:22:08.911 PropMemFun[2132:11303] ***
-[CFString respondsToSelector:]: message sent to deallocated instance
0x713ebc0

大概意思是:向已释放的内存发送消息。也就是说使用了已释放的内存,在C语言相当于使用了“野指针”

看了下crash的这个语句,sushiString应该是没问题的,它是从stringWithFormat初始化出来的。那就是_lastSushiSelected的问题。

_lastSushiSelected指向了sushiString,sushiString是一个autorelease变量。 在第二次点击时,使用的是sushiString已经被释放,所以crash了。那为_lastSushiSelected保留一下,就可以用了。代码修改如下:

[cpp] view plaincopy

  1. <span style="font-size:14px;">    _lastSushiSelected = [sushiString retain];

  2. </span>

运行,这时候不崩溃。

3、分析内存泄露(shift+command+b)


app不crash了,那看看有没有内存泄露。用XCode的Analyze就能分析到哪里有内存泄露

分析之后可以看到:

这里提示alertView没被释放,有内存泄露,那我们释放

[alertView release];

再分析,这个问题解决了。

4、使用Instruments的leaks工具

分析内存泄露不能把所有的内存泄露查出来,有的内存泄露是在运行时,用户操作时才产生的。那就需要用到Instruments了。

按上面操作,build成功后跳出Instruments工具,选择Leaks选项,这时候寿司程序也运行起来了,选中list中的项,拖动等操作后,工具显示效果如下:

大家可能都能猜到,红色的柱子表示内存泄露了。怎么通过这个工具看到在哪泄露了呢?

先在工具栏按下红色的圆形按钮,把工具监视内存的活动停下来。选择Leak,然后点中间十字交叉那,选择Call Tree.

这时候左下角的Call Tree的可选项可以选了。选中Invert Call Tree 和Hide System
Libraries,显示如下:

这时候内存泄露的具体代码找到了,在右边的红色框框里指定了哪个方法出现了内存泄露。

你只要在这些方法上双击,就会跳转到具体的代码,哈哈,是不是很方便。

这里应该是提示100%内存会泄露。

6、解决内存泄露问题

问题找到了,那就解决吧

关于:tableView:didSelectRowAtIndexPath ,分析下它的内存过程:

  1. sushiString变量通过autorelease创建,它的引用计数是1.

  2. 这行代码使得引用计数增加到2, _lastSushiSelected = [sushiString retain];

  3. 这个方法结束时,sushiString的autorelease生效了,这个变量的引用计数减少为1

  4. 当再次执行tableView:didSelectRowAtIndexPath这个方法时,_lastSushiSelected被赋值了新指针,老的_lastSushiSelected的引用计数还是1,没有被释放,产生了内存泄露。

怎么解决呢?

在_lastSushiSelected =
[sushiString retain];之前把原来的release就ok了:

[cpp] view plaincopy

  1. [_lastSushiSelected release];

  2. _lastSushiSelected = [sushiString retain];

关于:tableView:cellForRowAtIndexPath


这个比较明显,sushiString被alloc和init之后就没有释放,可以用stringWithFormat来调用autorelease,代码如下:

[cpp] view plaincopy

  1. NSString *sushiString = [NSString stringWithFormat:@"%d: %@", indexPath.row, sushiName];

好了,泄露都fix了,再用工具分析看看,这时候你再点,再拖,再怎么操作,都没有内存泄露了。表明内存泄露被堵住了。

利用leaks模板分析app的内存泄露,布布扣,bubuko.com

时间: 2024-10-24 10:41:32

利用leaks模板分析app的内存泄露的相关文章

[Android Memory] App调试内存泄露之Context篇(上)

转载自:http://www.cnblogs.com/qianxudetianxia/p/3645106.html Context作为最基本的上下文,承载着Activity,Service等最基本组件.当有对象引用到Activity,并不能被回收释放,必将造成大范围的对象无法被回收释放,进而造成内存泄漏. 下面针对一些常用场景逐一分析. 1. CallBack对象的引用 先看一段代码: @Override protectedvoid onCreate(Bundle state){ super.o

[Android Memory] App调试内存泄露之Context篇(下)

转载地址:http://www.cnblogs.com/qianxudetianxia/p/3655475.html 5. AsyncTask对象 我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncTask等系统自带类去做事情,当然无可厚非. 但是AsyncTask确实需要额外注意一下.它的泄露原理和前面Handler,Thread泄露的原理差不多,它的生命周期和Activity不一定一致. 解决方案是:在activity退出的时候,终止AsyncTask中的后台任务. 但是,问题是如

如何用MAT分析Android应用内存泄露

使用工具:Android Studio 2.0 Preview, Android Device Monitor, MAT(Memory Analyzer). 点击Android Studio工具栏上的“Android Device Monitor”,如下图 打开后选中应用进程,然后点击“Update heap”,接着反复点击应用的每个activity,最后“Dump HPROF file”,如下图1-2-3所示 保存hprof文件. 下面需要对hprof文件进行转换. 打开CMD终端,进入到\s

利用linux的mtrace命令定位内存泄露(Memory Leak)

一谈到内存泄露, 多数程序猿都闻之色变. 没错, 内存泄露非常easy引入. 但非常难定位.  以你我的手机为例(如果不常常关机). 如果每天泄露一些内存, 那么開始的一个星期, 你会发现手机好好的. 当内存泄露积累到一定程度,  那就是各种卡死了. 系统异常, 最后死机. 不得不重新启动. 假设搞开发. 遇到内存泄露问题, 那就呵呵了. 你可能先得花好几天来复现问题(泄露积累), 然后须要花好几天来定位问题和改动问题, 然后又要花好几天来验证问题, 并且. 非常有可能没法一次改好, 上述流程又

JVM NativeMemoryTracking 分析堆外内存泄露

https://blog.csdn.net/varyall/article/details/86514888 https://blog.csdn.net/weixin_33898233/article/details/91480055?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task 原文地址:https://www.cnblogs.com/diyunpe

【转】.. Android应用内存泄露分析、改善经验总结

原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194206.TASKID&ADUIN=554147273&ADSESSION=1467939955&ADTAG=CLIENT.QQ.5479_.0&ADPUBNO=26582 前言   通过这几天对好几个应用的内存泄露检测和改善,效果明显: 完全退出应用时,手动触发GC,从原来占有

内存泄露分析之MAT工具简单使用

使用了Heap视图的方式来分析内存泄露之后,我们尝试用MAT插件来分析下. MAT,提供了太强大的功能,以至于在测试的过程中也是懵懂的,没有彻底的研究. 1. 安装Android Sdk,Java SDK,Eclipse之类的软件之后, 2. 安装Eclipse MAT插件 3. 调出DDMS的Heap视图 4. 手机连接电脑之后,选择要测试的进程,并点击Heap 5. 在手机上操作需要测试的功能 6. 选择Dump HPROF file功能. 7. 如果Eclipse中直接安装了MAT插件之后

C++内存泄露和检测

C++中的内存泄露一般指堆中的内存泄露.堆内存是我们手动malloc/realloc/new申请的,程序不会自动回收,需要调用free或delete手动释放,否则就会造成内存泄露.内存泄露其实还应该包括系统资料的泄露,比如socket连接等,使用完后也要释放. 内存泄露的原因: 总结下来,内存泄露大概有一下几个原因: 1.编码错误:malloc.realloc.new申请的内存在堆上,需要手动显示释放,调用free或delete.申请和释放必须成对出现malloc/realloc对应free,n

使用gc、objgraph干掉python内存泄露与循环引用!

Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问题:内存泄露与循环引用.内存泄露是让所有程序员都闻风丧胆的问题,轻则导致程序运行速度减慢,重则导致程序崩溃:而循环引用是使用了引用计数的数据结构.编程语言都需要解决的问题.本文揭晓这两个问题在python语言中是如何存在的,然后试图利用gc模块和objgraph来解决这两个问题. 注意:本文的目标是Cpyth