在项目开发过程中,我们进行内存泄漏的排查时,会使用系统自带的 Analyze和Instruments 工具,但在使用过程中,它们存在了各种问题和不便,内存泄漏的定位有时候不是那么精准,今天向大家分享一款快速检测内存泄漏的开源库。
在这之前,我们先了解下内存泄漏,关于Leak(泄漏),在苹果的开发者文档里可以看到,一个 app 的内存分三类:
Leaked memory: Memory unreferenced by your application that cannot be used again or freed (also detectable by using the Leaks instrument).
Abandoned memory: Memory still referenced by your application that has no useful purpose.
Cached memory: Memory still referenced by your application that might be used again for better performance.
其中 Leaked memory 和 Abandoned memory 都属于应该释放而没释放的内存,都是内存泄露,而 Leaks 工具只负责检测 Leaked memory,而不管 Abandoned memory。在 MRC 时代 Leaked memory 很常见,因为很容易忘了调用 release,但在 ARC 时代更常见的内存泄露是循环引用导致的 Abandoned memory,Leaks 工具查不出这类内存泄露,应用有限。
对于 Abandoned memory,可以用 Instrument 的 Allocations 检测出来。检测方法是用 Mark Generation 的方式,当你每次点击 Mark Generation 时,Allocations 会生成当前 App 的内存快照,而且 Allocations 会记录从上回内存快照到这次内存快照这个时间段内,新分配的内存信息。举一个最简单的例子:
我们可以不断重复 push 和 pop 同一个 UIViewController,理论上来说,push 之前跟 pop 之后,app 会回到相同的状态。因此,在 push 过程中新分配的内存,在 pop 之后应该被 dealloc 掉,除了前几次 push 可能有预热数据和 cache 数据的情况。如果在数次 push 跟 pop 之后,内存还不断增长,则有内存泄露。因此,我们在每回 push 之前跟 pop 之后,都 Mark Generation 一下,以此观察内存是不是无限制增长。
用这种方法来发现内存泄露还是很不方便的:
首先,你得打开 Allocations
其次,你得一个个场景去重复的操作
无法及时得知泄露,得专门做一遍上述操作,十分繁琐
MLeaksFinder
我在这里向大家介绍MLeaksFinder这款非常好用的动态检测内存泄漏的开源库,是WeRead团队开源的一款检测 iOS 内存泄漏的框架。只需要引入 MLeaksFinder,就可以自动在 App 运行过程检测到内存泄露的对象并立即提醒,无需打开额外的工具,也无需为了检测内存泄露而一个个场景去重复地操作。MLeaksFinder 目前能自动检测 UIViewController 和 UIView 对象的内存泄露,而且也可以扩展以检测其它类型的对象。
Installation
可以直接使用Cocoapod导入,即可使用,无需添加代码:
pod 'MLeaksFinder'
导入工程之后,在Edit Scheme中设置 Profile->Build Configuration 为debug:
在App运行过程中检测到内存泄漏的对象后,会弹出alert警告,如下:
使用简单,不侵入业务逻辑代码,不用打开 Instrument
不需要额外的操作,你只需开发你的业务逻辑,在你运行调试时就能帮你检测
内存泄露发现及时,更改完代码后一运行即能发现(这点很重要,你马上就能意识到哪里写错了)
精准,能准确地告诉你哪个对象没被释放
只在Debug环境下生效,并不会影响Release环境
参考:WERead团队博客 MLeaksFinder