经验之道:最有效的iOS内存泄漏检测
版权声明:本文由胡涛原创文章,转载请注明出处:
文章原文链接:https://www.qcloud.com/community/article/125
来源:腾云阁 https://www.qcloud.com/community
使用instruments工具来更好的调试我们的工程中新开发或者修改过的模块的内存状况。
iOS设备性能越来越好,iOS App 也相应的变得越来越庞大,App代码的量级也在快速的增长,开发一个小的模块在工程中调试变的越来越难,通常我们是通过观察Allocation的内存变化高低,或者内存分配快照对比来寻找泄漏的情况,但这几乎是一个让人抓狂的调试方法,尤其在非常复杂的项目中,一个模块的推入与推出在Allocation上的变化微乎其微,而且受制于项目的复杂度,各种你所未知的对象的创建与销毁带来的Allocation图形高度的影响,对于观察Allocation的分配图像的高低变化来说,能够参考的意义就变的非常有限。
通过过去参与过的复杂大型的iOS项目开发经验,开发新的模块的时候,总结出了一套完整的iOS内存自测的方法,通过Instruments来逐步跟踪检测我们创建和主动销毁的对象是否真的销毁了。
在演示之前,需要强调一件事情就是,以文件夹目录作为你的空间命名很重要,请遵循开发新模块的时候使用你的模块的命名作为前缀。因为iOS没有命名空间这个东西,通常为了保证不冲突,我们都是以项目前缀+空间命名来保证文件的独立性,空间名就是目录和模块的名字了。这个在我们使用instruments进行内存检测的时候是非常重要的,接下来的使用过程就可以证实这一良好的命名习惯所带来的巨大好处,不只是优雅,更重要的是帮助。
除了命名,还有一件很重要的事情就是,你需要对你的模块在各种UI操作或者事件发生过程的情况下,对你的对象分配过程要非常非常清楚,因为这样,你才能看出相应的变化,哪些对象是应该存在的,哪些对象在某个动作结束后是必定会销毁的,这个应该很容易,你应该纯天然的就知道,因为你开发的整个逻辑。
最近在开发一个新的模块,正好需要在内存方面做一个完整的自测,既要确保效率,也要确保内存的正确分配与释放。
重要:(以下教程开始所有示例图片,请自行点击图片看大图,看的倍儿清楚!)
首先,我先上图,看一下我的命名组织结构,遵循的就是模块化的命名,因为手Q的跨部门合作,所以用部门标记作为前缀。代码首先是要让人来看的,是人在维护程序,所以可读性非常重要,在开发完这些功能后,我对于所有对象在运行过程中的创建与销毁是很清楚的。
接下来我要进入instruments来进行内存测试,profile运行Leaks就OK了,就会进入下面看到的界面,详细讲解一下都是什么吧,这些对对象怎么分配内存的很重要。
然后我就需要操作模拟器来进入我所开发的功能模块,会看到非常复杂的对象分配情况,所以这一步非常关键,我只需要在搜索框搜索模块的前缀就可以只显示当前模块所涉及的对象分配与销毁情况,如下图,进入了的模块视图:
接下来我执行一个环境查询的命令,再看一下执行之后的内存分配情况。
我的逻辑是这样的,点击一次创建一个命令(VASDebugPlatformServerCmd),通过这个命令初始化并执行一个任务,任务结束后就销毁这个任务对象(VASDebugPlatformBaseOperation),相应的命令也作为任务的成员一起被销毁。所以,在动作执行完后我们应该可以在已销毁对象中找到这个实例,运行截图如下:
我看到任务是已经被销毁了的,可是用来初始化的命令对象为什么没有被销毁,我需要深挖一下这个命令对象(VASDebugPlatformServerCmd)的引用计数到底怎么发生变化的,就需要用到下面的步骤了,按照图解去深挖它:
我挖到命令对象的内部,一路挖到底,我发现命令对象最终的引用计数是1,证明它还在内存中活着,截图是这样的:
所以,我就看看,任务对象销毁了,那任务对象到底发生了什么事 截图是这样的:
我就是不死心,我就是要看到,到底是不是真的呢,为了进一步佐证命令对象在内存中,我在对象内部观察了一个内存检测的通知,收到通知后弹一个alert出来,如果对象被销毁了,它肯定收不到这个通知,如下面截图所示的工作:
因为这是我自己写的逻辑,我很清楚对象在哪里分配内存,然后我就去查代码,命令对象到底经历了什么,从开始到结束的执行过程是什么样的:
- 看完上面的截图,再去看命令对象的引用计数变化就知道为什么了:
- 当然,我也看出了为什么引用计数没有归零,所以,我在下面进行了修复:
- 再次profile->Leaks , 然后我再做一次查询任务,看看这次命令对象的引用计数变化,命令对象被释放了!:
总结:
保持你的模块拥有一个良好的命名空间
请深刻并且清楚的知道,触发什么事件,执行UI动作之后,你的对象分配会是什么样的,谁此刻应该存在内存中,谁应该被销毁,然后利用上面的原理去查看,它是不是被销毁了,如果没有被销毁,那么你应该去查你的代码,到底在执行过程中,哪里没有平衡引用计数。
此方法在ARC和MRC的情况都是适用的,目标是观察具体哪个实例对象没有被销毁,然后根据引用计数变化跳转到代码中去确认哪里出现了内存问题。
文章来源于公众号:小时光茶社(Tech Teahouse)
经验之道:最有效的iOS内存泄漏检测的更多相关文章
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self
前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...
- iOS内存泄漏自动检测工具PLeakSniffer
新款objective-C内存泄漏自动检测工具 PLeakSniffer , GitHub地址 (https://github.com/music4kid/PLeakSniffer). 背景 前些天读 ...
- 【YFMemoryLeakDetector】人人都能理解的 iOS 内存泄露检测工具类
背景 即使到今天,iOS 应用的内存泄露检测,仍然是一个很重要的主题.我在一年前,项目中随手写过一个简单的工具类,当时的确解决了大问题.视图和控制器相关的内存泄露,几乎都不存在了.后来想着一直就那个工 ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug
前言: 话说昨晚还是前晚,写了一篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上) 文章写到最后时,多了很多莫名奇妙的问题!!! 为了解决了这些莫名奇妙的问题,我又战斗了2 ...
- iOS 内存泄漏监测自动化
在 Android 上,Square 这家公司提供了非常有名的工具: leakcanary ,来帮助开发者们在日常开发过程中就能够发现内存泄漏.但在 iOS 上呢?在 Google 的时候,我发现了两 ...
- 精准 iOS 内存泄露检测工具
MLeaksFinder:精准 iOS 内存泄露检测工具 发表于 2016-02-22 | zepo | 23 Comments 背景 平常我们都会用 Instrument 的 Lea ...
- Cocos开发中性能优化工具介绍之Visual Studio内存泄漏检测工具——Visual Leak Detector
那么在Windows下有什么好的内存泄漏检测工具呢?微软提供Visual Studio开发工具本身没有什么太好的内存泄漏检测功能,我们可以使用第三方工具Visual Leak Detector(以下简 ...
- C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- C++程序内存泄漏检测方法
一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准.而在W ...
随机推荐
- dac7562 应用层实现dac
/* * dac7562 (using spidev driver) * */ #include <stdint.h>#include <unistd.h>#include ...
- yum-plugin-priroites这个插件的一个文件。
yum源优先级的一个文件.是yum-plugin-priroites这个插件的一个文件.用来给yum源分优先级的.比如你在centos下有centos,epel,rpmfusion三个yum源.三个y ...
- 关于添加图片到svg中,rails下使用js, 用parseFloat来调整force.on时的位置
注意在代码中用/表示路径...windows中file才是\ 1.<image xlink:href=<%= asset_path 'vnet/virtual_switch.png' %& ...
- 利用层的table-row、table-cell属性进行页面布局
利用层的table-row.table-cell属性可以进行等高.宽度自适应页面布局,这是参看了<我所知道的几种display:table-cell的应用>及<基于display:t ...
- AJAX乱码解决新方法
用过AJAX的朋友肯定知道javascript是使用UTF-8国际编码,即每个汉字用3个字节来存储,但是这就造成了用AJAX来send数据的时候出现乱码. 有一种解决办法就是使用encodeU ...
- 关于Cocos2d-x中背景音乐和音效的添加
1.首先引入头文件和命名空间 #include "SimpleAudioEngine.h" using namespace CocosDenshion; 2.在GameScene. ...
- C++函数类型
继续上一篇 #include <iostream> using namespace std; void swap1(int &v1, int &v2); typedef v ...
- Ubuntu下启动/重启/停止apache服务器
Task: Start Apache 2 Server /启动apache服务# /etc/init.d/apache2 startor$ sudo /etc/init.d/apache2 start ...
- 腾讯企业邮箱POP,SMTP分别是什么
腾讯企业邮箱在做域名解析的时候不用做pop3和 smtp设置,可以使用下列的协议: POP3/SMTP协议 接收邮件服务器:pop.exmail.qq.com (端口 110),使用SSL,端口号 ...
- opengl 模板测试 glStencilOp glStencilFunc
下面来设置蒙板缓存和蒙板测试. 首先我们启用蒙板测试,这样就可以修改蒙板缓存中的值. 下面我们来解释蒙板测试函数的含义: 当你使用glEnable(GL_STENCIL_TEST)启用蒙板测试之后,蒙 ...