iOS内存泄漏自动检测工具PLeakSniffer 2018-01-11

转自 http://www.cocoachina.com/ios/20160706/16951.html

iOS内存泄漏自动检测工具PLeakSniffer

背景

前些天读到WeRead团队分享的一款内存泄漏检测工具MLeaksFinder,恍惚想起早些时候自己也有过编写这样一个小工具的想法,不知道由于什么原因把这事给忘记了。在仔细读过MLeaksFinder源码,了解实现思路之后,发现和自己最初的想法并不相同,终于在上个周末战胜拖延症将之前的想法付诸于代码,也就诞生了这款功能类似的内存泄漏检测工具PLeakSniffer。建议读者先详细阅读下MLeaksFinder这篇博客。

为什么要再造轮子

我在公司的项目里实际试用了MLeaksFinder,还查处了2处泄漏??。根据MLeaksFinder代码文件中日期推测,这个项目至少已开始半年有余,并在微信读书上得到了实践验证,在功能性和稳定性上都应该有不错的表现。

在编写完PLeakSniffer之后,查出了与MLeaksFinder相同的内存泄漏,思路迥异的代码抵达了相同的终点,写代码的乐趣莫过于此。新的思路或许还能抛砖引玉,如果激发更多的创意,也算是对iOS开发社区的一点小贡献。

MLeaksFinder现阶段能查处UIViewController和UIView的泄漏,我早先的想法还能递归的查出UIViewController之下所有Property的泄漏,并在PLeakSniffer及公司项目中得到了初步的验证,这算是对MLeaksFinder功能的一个小补充。

这类工具的意义

在我们讨论这类工具的意义之前,我们先得明确一点:

如果不使用Instrument当中的Leak检测工具,并没有什么轻易的100%精准的内存泄漏检测方式。

但这类工具还是有其存在价值的,内存泄漏的危害不用赘述,如果有一款工具能在80%的场景下检测出可能的内存泄漏,而且这种检测并不会带来任何副作用(不影响生产环境代码),为什么不使用它呢。

大部分人都低估了他们写代码时导致意外内存泄漏的可能性。Retain Cycle,Block强引用,NSTimer释放不当,这些常见的错误还是很容易出现在我们的代码里,Instrument每使用一次要费些精力,适合做定期的大排查。平常时候就更适合用MLeaksFinder,PLeakSniffer这类工具来做实时监控,提供免费建议。

PLeakSniffer实现思路

我们绝大部分时候都是在编写UIViewController,UIViewController就像一个根节点,持有并管理着很多的子节点对象,这些子节点的生命周期都依赖于Controller,Controller释放的时候,他们也随之释放。用一张图简单的描述他们的关系:

根据各个应用使用的设计模式不同(MVC,MVP,MVVM等),Controller所持有的Property也不相同。这里我们使用MVP作为例子,Controller所包含的对象就包括各种View对象,和Presenter,Model对象。当然每个对象又有可能持有更多的子对象。

PLeakSniffer基于这样一个假设:

如果Controller被释放了,但其曾经持有过的子对象如果还存在,那么这些子对象就是泄漏的可疑目标。

当然这个假设并不是一个100%适用的真理,不同工程师编写代码的方式风格差别很大,有些会把某些UIViewController做成单例(个人觉得这不是个好主意。。),有些会把某些View缓存起来(即使Controller已被释放),还会有其他考虑不到的场景。但在80%以上的场景,我们在Controller结束生命周期之后会将其持有的资源一并释放。这时候PLeakSniffer可以发挥用处,给你一些免费的泄漏建议。

那么怎么在Controller被释放之后,知道其持有的对象没有被释放呢?

一个小技巧可以达成这个目标:子对象(比如view)建立一个对controller的weak引用,如果Controller被释放,这个weak引用也随之置为nil。那怎么知道子对象没有被释放呢?用一个单例对象每个一小段时间发出一个ping通知去ping这个子对象,如果子对象还活着就会一个pong通知。所以结论就是:如果子对象的controller已不存在,但还能响应这个ping通知,那么这个对象就是可疑的泄漏对象。完整的结构可以用下图表示:

通知移除需要一个时机,这里我们使用Associated Object机制给每一个子对象再生成一个Proxy对象,在Proxy对象的dealloc里面移除通知。

当然什么时候去判断一个对象的生命周期开始,什么时候判断为结束,需要一个精挑细选的机制。View,Controller,Property各不相同。

PLeakSniffer采取保守的策略,通过Objective C的runtime机制,递归的将一个Controller所有强引用的property找出,并安装proxy监听Ping通知。在我的测试下,基本上能将property泄漏的场景找出。

PLeakSniffer的使用方式很简答,通过Pod安装后,通过以下代码激活即可

#if MY_DEBUG_ENV

[[PLeakSniffer sharedInstance] installLeakSniffer];

[[PLeakSniffer sharedInstance] addIgnoreList:@[@"MySingletonController"]];

#endif

addIgnoreList可以添加一些特殊的忽略名单,比如单例这种无法正确预测泄漏的对象。切记用Debug的宏将上述代码包住,不要把这些检测泄漏的代码带进线上环境。

如果检测到可疑泄漏,PLeakSniffer会在控制台打印一条日志:

Controller泄漏:Detect Possible Controller Leak: %@

其他对象泄漏:Detect Possible Leak: %@

GitHub地址:https://github.com/music4kid/PLeakSniffer

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容