原文链接地址: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执行你的代码和自动检测任何错误并警告你任何潜在的问题。它并不会找出所有的问题,但用这个方法找出的错误无疑是一个既快速又简单的方法。

  试一试通过选择Build\Build and Analyze。你应该看到,它检测到一个内存泄漏,你可以看到如下:

  消息显示,“alertView”有一个潜在的内存泄漏。如果你看看这一行,你就会发现所有的UIAlertView创造是有着alloc /init (返回一个对象引用数1),却从来没有真正地释放!有几种方法可以解决这个问题,但其中一个方法就是在[alertView show]下面加上一行:

[alertView release];

  再次 Build\Build and Analyze,你会发现已经找不出任何内存问题了。

泄漏和管道 

  不幸的是,你不能依靠Build\Build and Analyze找出一切问题。有一个强大的自动化工具来帮助你检查程序是否有内存泄漏– the Leaks Instrument。

  让我们试试看。选择Run\Run -> Performance -> Tool\Leaks,再选择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翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

子龙山人 Learning,Sharing,Improving! (译)怎样在xcode里面使用Memory Leaks和Instruments教程相关推荐

  1. 论文笔记-Learning to Predict Streaming Video QoE: Distortions, rebuffering and memory

    info Bampis C G, Bovik A C. Learning to predict streaming video QoE: Distortions, rebuffering and me ...

  2. Hybrid TLB Coalescing:Improving TLB Translation Coverage under Diverse Fragmented Memory Allocations

    Hybrid TLB Coalescing: Improving TLB Translation Coverage under Diverse Fragmented Memory Allocation ...

  3. Boosting Active Learning via Improving Test Performance

    文章来着第三十六届AAAI人工智能会议(AAAI-22) 概述: 主动学习(AL)的核心是应该选择哪些数据进行注释.现有的工作试图选择高度不确定或信息丰富的数据进行注释.然而,尚不清楚所选数据如何影响 ...

  4. 图构造总结-Graph‑based semi‑supervised learning via improving the quality of the graph dynamically

    前言 本博文主要对论文中提到的图构造方法进行梳理,论文自己提出的模型并未介绍,感兴趣的可以阅读原文 摘要 基于图的半监督学习GSSL主要包含两个过程:图的构建和标签推测.传统的GSSL中这两个过程是完 ...

  5. 子龙山人:我从Cocos2d-x团队里学到的那些事

    我是去年7月加入的Cocos2d-x团队,从今年2月份正式进入Cocos2d-x引擎团队,负责维护GUI框架.之前我一直在做技术推广,写英文教程.演讲.偶尔上课是我的全部工作.期间,我最骄傲的产出是出 ...

  6. (译)如何使用GameCenter制作一个简单的多人游戏教程:第一部分

    免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作 ...

  7. Cocos2d如何实现MVC

    子龙山人 Learning,Sharing,Improving! cocos2d里面如何实现MVC(完) 今天我们讨论的主题是Model-View-Controller (MVC)设计模式,以及如何在 ...

  8. Cocos2dx 实现擦除即橡皮擦效果的实现

    Cocos2dx实现橡皮擦效果的实现 DionysosLai(906391500@qq.com)  2014/8/25 之前项目在做一个绘本游戏,要求实现擦除效果,具体效果可以参考绘本<我是一只 ...

  9. (译)如何优化cocos2d程序的内存使用和程序大小:第二部分(完)

    转自:子龙山人 (译)如何优化cocos2d程序的内存使用和程序大小:第二部分(完) 前言:从上周发布教程的微博反应情况来看,cocos2der们对于游戏的内存问题还是非常关心的.本文是上一篇博文的续 ...

  10. 主动学习(Active Learning)领域部分经典论文汇总

    只简单找了一小部分 CVPR [link] Active Image Segmentation Propagation CVPR 16 segmentation [link] The Power of ...

最新文章

  1. GIS+=地理信息+云计算技术——Spark集群部署
  2. java基础 知识点
  3. Struts 动态FORM实现过程
  4. GitHub Actions,卧槽!牛批!
  5. AutoCompleteTextView组件的功能和用法
  6. Thread1:EXC_BAD_ACCESS 错误
  7. 30岁+程序员职场攻略:找到自己的“职业锚”乘风破浪
  8. PAT甲级1016 (map,排序)
  9. Bailian2684 求阶乘的和【迭代+函数+循环】(POJ NOI0105-34)
  10. python能做什么软件-Python能做什么
  11. oracle数据库的安全测试
  12. AAAI论文Joint Extraction of Entities and Overlapping Relations Using Position-Attentive Sequence阅读笔记
  13. Java sychronized关键字总结(一)
  14. 一级必杀,防不胜防的漏洞,WEB安全基础入门—文件上传漏洞
  15. 基于vue2的 H5框架
  16. 从未见过如此可笑的白领标准_独木桥的博客_雅虎博客_雅虎空间
  17. shell 004 __小斌文档 |数组+函数
  18. 静态HTML网页设计作品 仿唯品会购物商城(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 商城网站设计
  19. 2020 GDUT Rating Contest III (Div. 2) B - Loan Repayment 题解
  20. ffmpeg运行在服务器上,如何在脱离流媒体服务器的时候使用ffmpeg 监测.m3u8直播视频流的状态?...

热门文章

  1. 基于FlexRay总线的汽车冗余线控转向系统的可靠性(FEMA)分析
  2. Word正式文件的正规格式
  3. 中兴B860AV2.1-A,M,T-当贝纯净桌面-线刷固件(附刷机教程)
  4. H3C-云计算技术专题培训(分享六)
  5. 全国地图钻取(openlayers6+高德地图api行政区划)
  6. MySql 集群/主从
  7. php eclipse 插件安装,phpeclipse插件下载-phpeclipse插件官方版 v1.2.3 官方最新版 - 安下载...
  8. QQ音乐歌曲解析API接口
  9. 经典的股票/期货量化交易策略,拿来即用的Python策略源码
  10. 中国水系Android第一个版本