欢迎关注我的微信公众号“鱼在云中游”(hcytalk)。
对于检测iOS应用中的内存泄露,我们经常会用到Xcode自带的Instrument工具Leaks,但是Leaks使用起来不是很方便,对于初学者也很不友好,太多的信息需要筛选,还经常用着用着就检测不了得重启系统,让人不是很舒服。
所以今天介绍一下Github上的一个第三方iOS内存泄露检测工具MLeaksFinder,地址https://github.com/Tencent/MLeaksFinder,腾讯出品。
MLeaksFinder使用起来非常简单,只需要把它引入到你的项目里,一句额外的代码都不用加,只要应用跑起来了,它就会自动帮你检测有没有内存泄露。
MLeaksFinder的代码没有侵入性,这意味着你不用为了引入它而修改你原有的项目代码,甚至连发正式版都不用移除掉,因为它只在debug版本里起作用。
自动检测并弹框提醒,无需打开额外的检测工具,代码没有侵入性,无需一个个场景去重复操作,这就是MLeaksFinder的魅力所在。它默认只检测应用里UIViewController和UIView对象的泄露情况,因为一般应用里内存泄露影响最严重的就是这两种内存占用比较高的对象,它也可以在代码里设置扩展以检测其他类型的对象泄露情况。
如下面是被检测出有内存泄露时系统控制台输出的信息,同时应用内也会弹出对话框提示已有内存泄露发生。如下提示表示当前栈从上往下看,最后一个对象也就是MyTableViewCell的对象没被释放,在它之上的三个其他对象已经成功被释放了。
原理
一般情况下,当一个UIViewController被pop或者dismiss掉后,它的view和view的subview等也会很快地被释放掉,除非我们把它设置为单例或者还有强引用指向它。MLeaksFinder的做法就是根据这种基本情况,在一个UIViewController被pop或者dismiss掉3秒后,看看它的view和view的subview等是否还存在,如果还存在,就意味着有可能有内存泄露发生,弹框提醒用户。
循环引用链
看到这里你可能会问,MLeaksFinder虽然能帮我找到了泄露的对象,但是找到了之后却没告诉我应该怎么修改。
我们都知道,一般的内存泄露如果不是自己故意用强引用指向泄露的对象,那泄露的原因很有可能就是代码中出现了循环引用。MLeaksFinder只是帮用户找出了泄露的对象,却没有找出导致泄露的循环引用链条,用户还是得去看自己写的可能已经很久了的代码,然后花费很长的时间和功夫来找出为什么这个对象会销毁不了,想想就觉得不如放弃了,心寒。
其实山人自有妙计,我们会遇到的问题相信其他的开发者早就遇到过了。
Facebook在Github开源了一个用来检测循环引用的工具FBRetainCycleDetector ,地址https://github.com/facebook/FBRetainCycleDetector。使用这个工具可以传入应用内存里的任意一个Objective-C对象,FBRetainCycleDetector会查找以该对象为根节点的强引用树中有没有循环引用。
所以查找内存泄露现在一般是两个工具一起用,先用MLeaksFinder找出泄露的对象,然后再用FBRetainCycleDetector检测该对象有没有循环引用,如果有,根据找出来的循环引用链条去查看修改代码就方便很多了。
如下图是FBRetainCycleDetector检测出来的循环引用信息,这些信息表示MyTableViewCell对象有一个强引用指向对象_callback, _callback是一个__NSMallocBlock__类型的对象,_callback里又强引用了MyTableViewCell对象,这就是一个循环引用链。
看完这篇文章,是不是觉得以后查找内存泄露变得很easy了?
写于2018年4月7号。