使用Xcode和Instruments调试解决iOS内存泄露

 

来源:http://blog.csdn.net/totogo2010/article/details/8233565

虽iOS
5.0本子后入了ARC机制,由于彼此引用关系比较复杂时,内存泄露或可能是。所以了解原理非常重大。

这里讲述在没ARC的场面下,如何运用Instruments来寻觅程序中之内存泄露,以及NSZombieEnabled安装的使。

正文假而你曾比较熟悉Obj-C的内存管理机制。

试验的开发条件:XCode
4.5.2

1、运行Demo。

先期下充斥一个兑现准备好之内存泄露的Demo吧:leak
app

下载下来,打开运行,程序是一个寿司的列表,列出各种寿司卷。试着选择中的几乎履行,应该是择第二执行之早晚即便完蛋了。崩溃截图:

 

ACCESS 1

在倒的地方断住了,知道crash的地方了,但是非明了具体crash的来头。

 

2、设置NSZombieEnabled

即是一个 “EXC_BAD_ACCESS”错误。我们打开XCode的取舍项:“NSZombieEnabled”
。在crash时可能会见吃你更多之一部分提示信息。

设置步骤:1

ACCESS 2

2:勾上红框里的

ACCESS 3

运行,按刚才底操作选中内部的cell。再次crash,这次在output窗口会视多矣平等码错误信息:

 

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

约意思是:向已经放的内存发送信息。也就是说使用了都放出的内存,在C语言相当给采取了“野指针”

ACCESS 4

扣押了下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就能够分析到哪出内存泄露

ACCESS 5

剖析后可以望:

ACCESS 6

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

    [alertView release];

重新分析,这个题材解决了。

 

4、使用Instruments的leaks工具

解析内存泄露不可知把有的内存泄露查出来,有的内存泄露是于运行时,用户操作时才发的。那就算需因此到Instruments了。

ACCESS 7 

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

ACCESS 8

 

大家莫不都能猜到,红色的柱子表示内存泄露了。怎么通过这家伙看到于啊泄露了啊?

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

 

 

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

ACCESS 10

 

这会儿内存泄露的求实代码找到了,在右边边的红色框框里指定了哪位方法出现了内存泄露。

公而以这些措施及双击,就见面超越反到现实的代码,哈哈,是不是非常便利。

ACCESS 11

此间应该是提示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了,再就此工具分析看,这时候你更接触,再拖,再怎么操作,都不曾内存泄露了。表明内存泄露给挡住了。

即时是本文修复好之app代码:no
LeakApp

 

正文参考:http://www.raywenderlich.com/

 

 

相关文章