iOS内存泄露检测工具HJNSObjectRelease

By | 2014年10月12日

Demo:https://github.com/panghaijiao/HJNSObjectReleaseDemo

iOS内存泄露一直是程序猿需要注意的问题,目前来说,iOS官方提供内存泄露检测的工具主要是xcode instrument,网上相关文档比较多,在次就不再介绍。但是instrument检测有几个问题:

  1. 由于其功能过于强大,导致其检测时间比较长, 程序猿不可能经常使用;
  2. 无法检测一些特殊对象的泄露,如被单例引用过的对象,或者Block循环引用的对象;
  3. 内存泄露对象提示位置不准,其提示泄露的位置很多时候并不是对象实际泄露的位置,有可能是其引用类泄露所致,程序猿因此无法精准定位实际泄露对象,当然,对于高级程序猿,可能会详细追溯泄露的根源,不足在于代价较大。

本期主要介绍HJNSObjectRelease内存检测工具。
iOS对象生命期可以抽象为创建和释放两个过程,只有创建没有释放就表明该对象泄露。基于此原则,可以监控任何对象的创建和释放过程,那么问题来了,如何检测对象的创建和释放?

基于oc动态语言的特性,在对象init之前为对象创建一个通知监听,同时在对象dealloc时将其从监控中移除

此时,通过发送通知,那些泄露的对象由于没有调用dealloc函数(没有将自己从监控中移除)就会将自己的class打印在控制台,所有泄露对象一目了然。

发送通知可以设定在任意时刻,比较好的方式是在AppDelegate对象中

使用方法:

以测试view为例

此时控制台就会列出泄露的所有对象,是不是很简单!


PS:iOS9启动卡死问题已修复 2016/3/31

16 thoughts on “iOS内存泄露检测工具HJNSObjectRelease

  1. Terry Tang

    看了你的文章,有两点疑问?
    1. 你method swizzling了init方法。那么OC中默认的init方法是否没有被调用到了?
    2.看你文章中的代码,发现只有init方法的swizzling,那么dealloc方法呢?应该跟init方法的swizzling差不多。但是想问下。同样的框架中默认的dealloc方法应该是不会被调用到。
    如何保证编译器为dealloc添加的代码都被执行了呢?
    希望能够交流下想法。谢谢!:)

    Reply
    1. 庞海礁 Post author

      1、本工具的核心就是swizzling对象的init和dealloc方法,在自定义的方法里面只是增加了监听,最后还是会回调系统的init的方法的,所以不会影响对象的init和dealloc方法!
      2、dealloc也被swizzling了,具体可以查看代码,swizzling针对所有NSObject对象都有效,属于动态运行的,正常情况swizzling函数都会执行,除非被其它 swizzling给覆盖!

      Reply
  2. tidy

    楼主,怎样区分leak的对象和正处生命周期中的正常对象,代码中貌似所有没有dealloc的对象都能打印出来。

    Reply
    1. 庞海礁 Post author

      是这个的,本工具的主要目的是快速检测所有没有被释放的对象,包括单例对象等,比较适合分模块检测,要区分是否leak对象还是推荐instruments工具,具体区别及使用场景可以查看文章详细解决!

      Reply
  3. Pingback: [转] iOS — “自释放”在iOS开发中的应用 - 移动开发 - 阿里欧歌

  4. Pingback: [转]iOS—"自释放"在iOS开发中的应用 | 安卓文档网

    1. 庞海礁 Post author

      建议在模拟器8.X版本运行,9.X版本系统改动较大,有点问题~

      Reply
    1. 庞海礁 Post author

      NSObject可以检测到,只是由于没有任何价值,被过滤掉了

      Reply
  5. 匿名

    请问,dealloc方法的调用不是根据计数器来判断的吗?
    你是怎么知道什么时候该调用dealloc
    还有就是没有调用dealloc的对象不一定是内存泄漏吧? a 引用 b , c 引用 b , a dealloc了 b并没有dealloc,这个时候b的监听没有执行, 那 b 是内存泄漏吗?
    搞不懂这个逻辑

    Reply

回复 庞海礁 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注