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

虽然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保留一下,就可以用了。代码修改如下:

 

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

</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 ,分析下它的内存过程:

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

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

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

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

怎么解决呢?

 

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

 

[_lastSushiSelected release];   

    _lastSushiSelected = [sushiString retain];   

 

 

关于:tableView:cellForRowAtIndexPath

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

 

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

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

 

 

 

转载自:  http://www.cocoachina.com/newbie/basic/2012/1204/5242.html

转载于:https://www.cnblogs.com/Xer-Lee/archive/2013/06/06/3120538.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376625.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0755、0644、0600 linux文件权限

0755->即用户具有读/写/执行权限&#xff0c;组用户和其它用户具有读写权限&#xff1b; 0644->即用户具有读写权限&#xff0c;组用户和其它用户具有只读权限&#xff1b; 0600->仅拥有者具有文件的读取和写入权限

[Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法

在我前面的自定义裁剪窗口的代码中&#xff0c;我把裁剪的view放在了大的scrollview里&#xff0c;这样就出现了程序只能触发scrollview&#xff0c;无法操作我的裁剪窗口。所以我加了那篇博客下面最后两段代码。其实我遇到这个问题的时候是在一个scrollview里添加了一个Editte…

带点击事件的Spinner

最近有一个蛋疼的需求&#xff0c;在下拉框中&#xff0c;如果只有一个值&#xff0c;默认显示出来&#xff0c;有两个或者没有显示请选择&#xff0c;没有点击不弹框&#xff0c;但是要清空&#xff0c;两个点击开要移掉请选择字样的项 本来以为很简单&#xff0c;后来发现没有…

linux进程间通信快速入门【二】:共享内存编程(mmap、XSI、POSIX)

文章目录mmap内存共享映射XSI共享内存POSIX共享内存参考使用文件或管道进行进程间通信会有很多局限性&#xff0c;比如效率问题以及数据处理使用文件描述符而不如内存地址访问方便&#xff0c;于是多个进程以共享内存的方式进行通信就成了很自然要实现的IPC方案。LInux给我们提…

ROBOTS.TXT屏蔽笔记、代码、示例大全

自己网站的ROBOTS.TXT屏蔽的记录&#xff0c;以及一些代码和示例&#xff1a; 屏蔽后台目录&#xff0c;为了安全&#xff0c;做双层管理后台目录/a/xxxx/&#xff0c;蜘蛛屏蔽/a/&#xff0c;既不透露后台路径&#xff0c;也屏蔽蜘蛛爬后台目录 缓存&#xff0c;阻止蜘蛛爬静态…

五大主流浏览器 HTML5 和 CSS3 兼容性比较

转眼又已过去了一年&#xff0c;在这一年里&#xff0c;Firefox 和 Chrome 在拼升级&#xff0c;版本号不断飙升&#xff1b;IE10 随着 Windows 8 在去年10月底正式发布&#xff0c;在 JavaScript 性能和对 HTML5 和 CSS3 的支持方面让人眼前一亮。这篇文章给大家带来《五大主流…

Ubuntu下将Sublime Text设置为默认编辑器

转自将Sublime Text 2设置为默认编辑器 修改defaults.list 编辑/etc/gnome/default.list文件&#xff0c;将其中的所有gedit.desktop替换为sublime_text.desktop。 sublime_text.desktop在/opt/sublime_text目录下&#xff0c;使用ls -al *sublime*命令查看具体文件名。 转载于…

python获取最近N天工作日列表、节假日列表

# 获取最近两周工作日列表、节假日列表 import datetime import chinese_calendar import time import pandas as pd# 将时间戳转换成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把时间…

保存页面的浏览记录

我的设计思想是将用户的浏览记录保存到cookie里面&#xff0c;然后根据情况处理。cookie里面的数据格式是json格式&#xff0c;方便根据自己的需要添加或者修改属性。引用了3个js文件,下载地址如下。 https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js …

开窍小老虎,一步一个脚印之 初识汇编(一)

最近一直浸淫在计算机编程中无法自拔。哲学 认识论中讲过。人类的求知的过程是由两次飞跃。第一是从感性认识到理性认识&#xff1b;第二是从理性认识到实践。这段话对有些人是适用的。我就是其中的一名。在知乎上求助问题“学计算机要懂汇编吗&#xff1f;”&#xff0c;地下有…

python脚本 请求数量达到上限,http请求重试

由于在内网发送http请求同一个token会限制次数&#xff0c;所以很容易达到网关流量上限。 业务中使用了多线程并发&#xff0c;一个线程发起一次http请求&#xff0c;得到正确结果后返回。这里采用的策略是&#xff0c;如果解析出来达到流量上限&#xff0c;那么该线程休眠一段…

shell 字符串操作

string"abcABC123ABCabc" 字符串长度: echo ${#string} #15 echo expr length $string #15 索引 用法&#xff1a;expr index $string $substring expr index $string "ABC" #4 提取子串 用法&#xff1a;${string:position} echo ${string:3} #A…

Linux 之目录 -鸟哥的Linux私房菜

因为利用 Linux 来开发产品或 distributions 的社群/公司与个人实在太多了, 如果每个人都用自己的想 法来配置档案放置的目录,那么将可能造成很多管理上的困扰。 你能想象,你进入一个企业之后,所 接触到的 Linux 目录配置方法竟然跟你以前学的完全不同吗? 很难想象吧~所以,后来…

python脚本:向表中插入新数据,删除表中最旧的数据

一张表存储历史数据&#xff0c;最多存储HISTORY_TABLE_MAX_ROWS条数据&#xff0c;当表中数据未达到HISTORY_TABLE_MAX_ROWS&#xff0c;直接插入&#xff1b;如果达到的话需要保证插入新数据的时候将最旧的数据删除 这里使用先update最新数据&#xff0c;然后再重新update全表…

精通 VC++ 实效编程280例 - 02 菜单和光标

菜单和关闭时重要的 Windows 资源之一。SDK 中&#xff0c;用 HCURSOR 和 HMENU 分别表示菜单和光标的句柄。MFC 中&#xff0c;CMenu 类封装了菜单的功能。 23 动态添加和删除菜单项 添加菜单项可以调用 CMenu::AppendMenu 或 CMenu::InserMenu 函数&#xff0c;删除菜单项可以…

POJ 1860: Currency Exchange 【SPFA】

套汇问题&#xff0c;从源点做SPFA&#xff0c;如果有一个点入队次数大于v次&#xff08;v表示点的个数&#xff09;则图中存在负权回路&#xff0c;能够套汇&#xff0c;如果不存在负权回路&#xff0c;则判断下源点到自身的最长路是否大于自身&#xff0c;使用SPFA时松弛操作…

python脚本:判断字符是否为中文

# 判断字符是否为中文 def is_chinese(ch):if u\u4e00 < ch < u\u9fff:return Trueelse:return False

Android 广播 Broadcast学习

Android Broadcast 广播 进程内本地广播 如果你是在你的应用之内使用广播&#xff0c;即不需要跨进程&#xff0c;考虑使用LocalBroadcastManager &#xff0c;这样更有效率&#xff08;因为不需要跨进程通信&#xff09;&#xff0c;并且你不用考虑一些其他应用可以发送或接收…

python:将时间戳转换成格式化日期

import time # 将时间戳转换成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把时间戳转换成时间元祖result time.strftime(format, time_tuple) # 把时间元祖转换成格式化好的时间retur…

WebApp 里Meta标签大全

1.先说说mate标签里的viewport&#xff1a; viewport即可视区域&#xff0c;对于桌面浏览器而言&#xff0c;viewport指的就是除去所有工具栏、状态栏、滚动条等等之后用于看网页的区域。对于传统WEB页面来说&#xff0c;980的宽度在iphone上显示是很正常的&#xff0c;也是满屏…