-
怎样在xcode里面使用Memory …
2013-08-03 02:14:44原文地址:Leaks和Instruments教程【检测内存泄露】">怎样在xcode里面使用Memory Leaks和Instruments教程【检测内存泄露】作者:我还是我 怎样在xcode里面使用Memory Leaks和Instruments教程【检测内存泄露】 ...怎样在xcode里面使用Memory Leaks和Instruments教程【检测内存泄露】
原文链接地址:http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial
免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!
本文由yy翻译。Powered by YY!:)
教程截图:
作为一名无证程序员,无论你多么精通Objective-C的内存管理,随着时间的推移,你也不可避免的犯内存相关的错误。但通常因为代码量太大,以至于你不可能一行一行的去排除(等你解决完,你设计的动车早相撞了!)
幸运的是,苹果已经提供了一些好的方式来帮助你找到应用程序中内存相关的问题。有时,这些工具可能吓到初学者,但它们实际上相当有用并易于掌握!
这就是本教程说要介绍的.你会亲手使用内存工具在XCode环境下很轻松的检测内存问题。
这篇教程是建立在你非常熟悉Objective-C内存管理的基础上。如果你还在这个问题上找不着北,你可能需要学习内存管理其他教程。
第一步
在这一节中,我们的目的是在一个例子应用程序中检查、解决任何内存泄漏问题,以演示常见的内存相关错误处理。开始,下载一个应用程序示例。我已经将教程和示例工程文件放在一起了。
在XCode中打开工程并运行。你会看到tableview中包含了一个寿司列表。试着选择几行,然后——轰!你看到可怕的EXC_BAD_ACCESS错误,编译器拿它完全没有办法。
因为xcode完全没指出出问题的地方,所以这种情况通常令许多开发者感到郁闷。当你遇到了一个EXC_BAD_ACCESS错误,我通常会给开发者几个建议:
1.在可执行选项中设置NSZombieEnabled参数,这有时会帮缩小问题的范围;
2.运行apple的内存检测工具,如 Leaks ,以便寻找内存问题;
3设定一个断点,单步运行代码,直到你找到引起崩溃的位置;
4.注释代码,直到不崩溃为止,然后再从后往前查找错误;
现在让我们从第一条开始实验
# 1 - NSZombieEnabled参数
一大波僵尸正在靠近!!!!
不幸的是,NSZombieEnabled选项对于崩溃毫无办法,所以你完全可以放弃抵抗。
当你试图使用一个已经被销毁的对象,NSZombieEnabled会标志一个警告,所以NSZombieEnabled只是一个flag。这是一个良好的开端,因为大多数崩溃的原因都是使用了已经销毁的对象。
按照以下设置:在XCode中展开Executables->双击PropMemFun->选择Arguments选项卡->“Variables to be set in the environment”点击加号按钮。把变量名值设置成NSZombieEnabled,把值设置成YES,如下图:(xcode4在左上角,edit schema里面)
重新运行app,随便操作下使程序崩溃。查看下console log你就会看到如下信息:
2011-02-0312:07:44.778 PropMemFun[27224:207] ***
-[CFString respondsToSelector:]: message sent to deallocated instance ...这个程序将在很精确的一行暂停。崩溃后,你可以通过选定第一个区域,回溯找出导致崩溃的准确行数。比如现在这个示例就崩溃在:tableView:didSelectRowAtIndexPath。
不管你信不信,反正找出了出问题的那行。导致崩溃的问题就是向已经销毁的string发送了一个消息。这一行用了两个string:_lastSushiSelected和sushiString.
因为这个string是由stringWithFormat初始化,所以看起来程序是没有问题了,因为stringWithFormat的返回值是自动释放的,所以在下次使用前应该是安全的。但是 _lastSushiSelected的安全性如何呢?
虽然_lastSushiSelected是在sushiString执行到最后才赋值的。但是sushiString是自动释放的,所以有些时候sushiString被释放了,内存也被销毁。但是紧接着_lastSushiSelected 仍然有可能指向被销毁的内存!这就解释了崩溃原因:向已经销毁的内存发送消息导致崩溃。
我们只需保留_lastSushiSelected就可以解决这个问题,把最后一行改成下面的样子:
_lastSushiSelected = [sushiString retain];
再次运行程序,你会发现程序已经畅通无阻了。
编译,分析和总结
至少,我们有一个不崩溃的应用程序——这是一个好的开始。但接下来,我们需要开始确保没有任何内存泄漏。
有一种简单的方法可以初步确认你的程序在初始化中是否有任何内存泄漏或其他问题--使用内置编译和分析功能(built-in Build and Analyze)。
这将使XCode执行你的代码和自动检测任何错误并警告你任何潜在的问题。它并不会找出所有的问题,但用这个方法找出的错误无疑是一个既快速又简单的方法。
试一试通过选择BuildBuild and Analyze。你应该看到,它检测到一个内存泄漏,你可以看到如下:
消息显示,“alertView”有一个潜在的内存泄漏。如果你看看这一行,你就会发现所有的UIAlertView创造是有着alloc /init (返回一个对象引用数1),却从来没有真正地释放!有几种方法可以解决这个问题,但其中一个方法就是在[alertView show]下面加上一行:
[alertView release];
再次 BuildBuild and Analyze,你会发现已经找不出任何内存问题了。
泄漏和管道
不幸的是,你不能依靠BuildBuild and Analyze找出一切问题。有一个强大的自动化工具来帮助你检查程序是否有内存泄漏– the Leaks Instrument。
让我们试试看。选择RunRun -> Performance -> ToolLeaks,再选择table view中的几行。也可以上下滚动table view,从table view顶端到底部。基于前面的经验,你就应该开始看出一些蓝色的标签出现在泄漏的内存上。
点击停止按钮,然后去工具栏中点击“Leaked Blocks”让他变成“Call Tree”。在面板左下角,点击“Invert Call Tree”、“Hide System Libraries”。你将会看到这个工具发现两个不同的函数存在内存泄漏,你可以看到如下:
如果你双击一个函数的名字,它会带你直接到存在内存泄露的这行代码。这可以给你一个很好的错误位置提示,如果你查看代码并加以思考,你应该能够找出问题所在并解决它。
所以,为什么不看看代码,并且看看你是否能找出问题所在并修正吗?一旦你作出修改,并且能够无错误提示的跑Leaks。如果通过,表示你完成了
…
…waiting…
…
…waiitng…
…
…waiting…
…!
你已经搞定了,不管你信不信,反正我是信了。
解释一下
tableView:didSelectRowAtIndexPath
Leaks 告诉我们,这个问题的原因是字符串sushiString创造和存储过程中引起的内存泄漏。所以让我们一步一步的分析一下原因:
1.当sushiString被创建时,调用stringWithFormat。返回一个对象数值1并且发送autorelease消息。
2.在方法的最后一行,你在sushiString加入retain(retain数值增加到2)并将其存储到_lastSushiSelected。
3.后来,autorelease生效,retain数递减为1。
4.下一个tableView:didSelectRowAtIndexPath方法被调用,你重写_lastSushiSelected变量的一个指针指向一个新的字符串,- - - - -如果没有释放旧的! 所以那个老字符串并没有被释放仍然存在。
一个解决办法是增加下面一行在初始化lastSushiSelected sushiString之前:
[_lastSushiSelected release];
tableView:cellForRowAtIndexPath
就像在前面的方法,创建和存入名为sushiString的变量引起内存泄漏。以下是引起问题的分析:
1.一个新的字符串被alloc/init方法创建。
2.返回一个对象引用数 1.
3.然而,这个计数从来不减少,所以有一个内存泄漏!
这可以通过三种方式中的一种解决:
1.设置textLable为一个字符串后在sushiString中调用release方法。
2.alloc/init方法初始化完毕后在sushiString中调用autorelease。
3.用stringWithFormat代替alloc/init方法,返回一个已经标志为自动释放的字符串。
验证 leaks!
修正前面提到的问题,再次运行leaks,你会得到一个没有任何内存泄漏的app。
接下来该干什么?
这个链接可以下载到一个已经解决上述问题的工程文件。
最重要的是,你必须亲自实践使用NSZombieEnabled,Build and Analyze,和Leaks Instrument工具来找到内存泄漏。你应该能够很快把这项技术运用到你的工程中。
如果你有更好的方法,可以在下面评论,我也积极采纳大家的建议。
著作权声明:本文由http://www.cnblogs.com/andyque翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!
-
在Xcode里面跑OpenCL成功,添加fra…
2017-04-21 10:51:02 -
我用的是vs 2008,为什么在类里面…
2014-09-25 13:23:41我用的是vs 2008,为什么在类里面不能直接引用 OracleClient? 我的现象是这样的,录入System.Data. 后,出现的提示没有OracleClient,请问还需要特别的引入什么类库吗?如是是的话,如何引入? 最佳答案 ...我用的是vs 2008,为什么在类里面不能直接引用 OracleClient? 我的现象是这样的,录入System.Data. 后,出现的提示没有OracleClient,请问还需要特别的引入什么类库吗?如是是的话,如何引入?
最佳答案项目文件上点击右键,选择添加引用,然后找到.net选项卡的System.Data.OracleClient,点击确认即可。
-
vs2008有的类在类视图里面找不到的…
2014-03-19 21:09:37如题 按网上找到的方法 保存文件,关闭VS2008,删除下面这些配置文件,重启VS即可 .sou,是个隐藏文件 .clw,没找到,可能在VC6.0里有吧 .aps .ncb如题按网上找到的方法保存文件,关闭VS2008,删除下面这些配置文件,重启VS即可.sou,是个隐藏文件.clw,没找到,可能在VC6.0里有吧.aps.ncb -
在pwntools里面调用gdb
2020-04-04 23:46:51在pwn里面,几个重要的工具有IDA,ollydbg,gdb(pwndbg,peda…),pwntools等 IDA是比较全面的工具,界面也比较友好,但是动态调试elf比较麻烦,需要选中remote linux debugger,详见IDA+pwntools环境搭建,这里... -
python27怎么安装thrift解压包_早上发现我安装的thrift在python里面无法import。 >>> imp…...
2020-12-12 07:59:54早上发现我安装的thrift在python里面无法import。>>> import thrft.ThriftTraceback (most recent call last):File ““, line 1, in ImportError: No module named thrft.Thrift我是通过easy_install安装... -
通过Python访问XAMPP里面的MySQL数…
2017-10-10 16:51:13最近想在Python里面调试以下MySQL,想快速地搭建起MySQL+PHP的环境,于是用到了XAMPP, 下面是使用中遇到的一些问题. 操作系统为 Ubuntu 11.04 XAMPP 使用官网提供的 1.7.7 python 使用系统自带的 2.7.1 ptyhon需要通过... -
图片 + 文字 在一个 div 里面实现…
2018-04-09 11:53:50<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "content mod-cs-content text-content clearfix"> 最直观的解决方法 -
在IDEA里面如何启动部署web模板
2020-11-18 18:13:59我们在写项目的时候,可能不同的项目运用的Tomcat不一样,所以建议我们把部署的Tomcat的名字修改一下 如下:点击这里的Edit… 进入到这里 这里就是我们设置我们的Tomca的地方,红笔标注那里是改名的,一般改成和当前... -
Idea在html里面的快捷键
2018-11-06 18:34:37Ctrl+Alt+I,将选中的代码进行自动缩进编排,这个功能在编辑 JSP 文件时也可以工作 Ctrl+Alt+O,优化导入的类和包 Ctrl+R,替换文本 Ctrl+F,查找文本 Ctrl+Shift+Space,自动补全代码 Ctrl+空格,... -
[2014-09-25]对于Xcode6里面反射(p…
2015-06-26 09:20:22在xcode5里面的反射机制即:property_getName的方法中,不会获取到我认为是隐藏类型的属性,比如:hash,superclass,description,debugDescription这4个属性,但是在xcode6里面,反射时,会把hash值,superclass,... -
在csdn里面如何转载别人的文章
2020-02-13 22:08:44对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间里面,当然... -
IE 阻止了iframe里面应用生成…
2016-05-31 14:22:051.页面里的COOKIE不能是浏览器进程的COOKIE(包括验证票和不设置超时时间的COOKIE),否则跨域会...2.当利用IFRAME时,记得要在相应的动态页的页头添加一下P3P的信息,否则IE会自觉的把IFRAME框里的COOKIE给阻止掉,产生问题. -
如何在博客园里面转载他人的文章
2019-04-26 15:33:00对于喜欢逛博客的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间里面,当然... -
如何在Eclipse里面查看JDK源代码
2019-04-20 21:48:52方法一: 1. 打开你的Eclipse,然后随便找一个Java文件,随便找一个Java类库,比如String,然后按住Ctrl,再点击它,你会发现跳到如下界面: ...3. 在弹出的对话框中,找到JDK安装目录下的src.zi... -
【PHP】smarty里面的caching的三个…
2014-08-19 16:16:30分过程来说: 第一次设置缓存: $smarty->caching ...编译后会在cache_dir里生成一个缓存文件,这个文件里包含有此次生成缓存文件时的cache_lifetime,就是300秒; 然后修改 $smarty->caching -
在EDK里面添加ISE IP core的方法
2019-09-25 00:57:27(1)在ISE下,使用core generator,可以得到xilinx的IP的*.v和*.ngc文件,将这两个文件拷贝出来; (2)在EDK下使用“Create or Import Peripheral …”可以定制用户自己的IP(具体过程请参照相关资料),在生成... -
如何在eclipse里面查看java的源码
2019-11-01 20:30:181.鼠标靠近你要查看源码的函数,并找到这个 Open Declaration。 2.点击进去之后,你会发现,你什么也看不懂 这是因为这些是编译后的class文件,看不懂也正常 3.点击菜单栏的 Window——Preferences——Java——... ... -
14.Idea在html里面的快捷键
2018-12-14 11:09:00在当前行前面新建行 Ctrl+Shift+N 查找文件 ctrl_alt_t:选中代码可以添加try catch等 2、zencoding-输入左边缩写,按下tab键就ok啦(在html里的快捷键) html:5 HTML5 结构... -
可以在方法里面传n个相同类型数据吗?在不知道个数的情况下
2019-08-24 21:12:04当我们想在方法里面定义未知个数的参数时,我们可以用可变参完成; 示例 public class MyMath { public double add(double… param) { //三个点表示可变参; 我们传的是double类型数据,后面param是传入的double类型... -
cPanel里面看不到.htaccess文件 但…
2012-11-05 11:05:52标题看起来有一点矛盾看不到又...在FTP中.htaccess文件是可见的,如果在FTP中看不到.htaccess文件就下载一个新版的FTP软件就可以看到了。 就国外空间而言如果把.htaccess文件用FTP下载回来编辑,通常是用记事本打开 -
在Angular中使用Ant Design of Angular里面的小图标
2019-04-22 11:00:09公司在开发一个Angular的项目,里面用到了Ant Design of Angular的Icon。 出现了 origin ‘null’ has been blocked by CORS policy… 的问题 解决方法: ... -
Palm SDK 在Firefox里面跑起来了
2009-07-03 20:35:00主要修改是framework.js的最后一句话与firefox里面的冲突了,将其该为window.onload=function() { ….. } 就可以了。以后在弄张截图。 -
Qt4: Show an image in your widget – 在Qt里面显示图像
2012-03-24 15:26:00很多人问,怎么快捷的在Qt里面显示图像。 个人以为,在Qt里面你的widget上显示图像的最简单方法就是用QImage和QPaint。方法如下。 假设我们现在已经有了一个QImage的object。怎么有的,这里不管。 QImage *... -
在pycharm里面配置autopep8(win10 图解教程)
2020-03-28 12:40:10pycharm配置autopep8 一、打开pycharm ... 二、进入这个界面 1、在搜索栏上输入autopep8 2、选择autopep8 3、点击Install Package等待安装 4、返回上个页面查看autopep8安装成功 三、配置autopep8 1、返... -
在工程里寻找各种对象(如:右键菜单pop1,在menus里面寻找)
2016-04-18 16:24:42要充分利用PB的File——>Open… -
求助各位大神,本人安卓小白!想在官方底包里面添加magisk!如何实现!
2019-03-20 16:21:49我想在官方底包里面添加magisk,从而实现刷底包机器就有root权限的功能,请问我如何可以实现呢? 可以有偿求助!期待各位大神鼎力相助! 并且想问这种方法是不是通用… … 就是各厂商之间会不会有差异… 底包是Motorola...
-
Opencv判断颜色相似的图片
-
用Go语言来写区块链(一)
-
MySQL 触发器
-
rslogix5000软件工具介绍.pdf
-
Keil V5.2X环境 无法烧录 STLink无法更新固件
-
Galera 高可用 MySQL 集群(PXC v5.6 + Ngin
-
MySQL 多实例安装 及配置主从复制实验环境
-
小程序 | 微信小程序多图上传(点击上传、可修改删除与放大回显)
-
gitee【 码云】使用 Pull Request 功能进行代码审查的操作
-
【C++】容器适配器-----stack、queue、priority_queue
-
2014年重庆理工大学《算法分析与设计》三套期末考试试卷.pdf
-
Java Scanner的进阶使用 -04天 学习笔记
-
Python基础之定义变量、运算符、if语句
-
MySQL 查询与高级查询(多表、嵌套和正则表达式)
-
运算符
-
区块链公开课(下).pdf
-
《文件和目录操作命令》
<2.> -
Navicat Premium.rar
-
云开发后台+微信扫码点餐小程序+cms网页管理后台 含后厨端和用户端
-
春江水暖鸭先知.zip