替代Instrument的精准 iOS 内存泄露检测工具:MLeaksFinder

在项目开发过程中,我们进行内存泄漏的排查时,会使用系统自带的 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,可以用 InstrumentAllocations 检测出来。检测方法是用 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:


替代Instrument的精准 iOS 内存泄露检测工具:MLeaksFinder_第1张图片


在App运行过程中检测到内存泄漏的对象后,会弹出alert警告,如下:


替代Instrument的精准 iOS 内存泄露检测工具:MLeaksFinder_第2张图片


使用简单,不侵入业务逻辑代码,不用打开 Instrument

不需要额外的操作,你只需开发你的业务逻辑,在你运行调试时就能帮你检测

内存泄露发现及时,更改完代码后一运行即能发现(这点很重要,你马上就能意识到哪里写错了)

精准,能准确地告诉你哪个对象没被释放

只在Debug环境下生效,并不会影响Release环境

参考:WERead团队博客 MLeaksFinder

你可能感兴趣的:(替代Instrument的精准 iOS 内存泄露检测工具:MLeaksFinder)