MLeaksFinder学习记录

  • 不久之前的学习笔记了,整理下~
  • 结合源码看更佳~

内存泄露检测

  • Leaks检测leaded memory,Allocations通过MarkGeneration检测abandoned memory(仍然被引用但是没用的内存),操作麻烦,不够及时精准定位
  • MLeaksFinder:无侵入,即时,无需为了检测内存泄露重复操作某个场景。精准定位是哪个对象没释放。有白名单机制;目前只检测ViewController和View对象(可扩展,MLCheck())

原理

入口

  • [MLeaksFinder start]; //进行swizzle
  • [MLeaksFinder stop]; //设置静态局部参数,为NO,hook的函数不会执行到关键代码

NSObject

  • 添加willDealloc方法
    • 检测该对象是否在白名单内,白名单通过类判断
    • 判断该对象是否是上一次发送action的对象,是的话,不进行内存检测
    • 弱指针指向self,3s延迟,若被释放,给nil发消息直接返回,不触发断言,认为已经释放
  • assertNotDealloc
    • 判断leakedObjectPtrs跟对象的父节点集合有交集,则说明父节点已经弹过,无需再处理
      • [MLeakedObjectProxy isAnyObjectLeakedAtPtrs:[self parentPtrs]]
    • [MLeakedObjectProxy addLeakedObject:self]; //内部调用弹alert
  • NSObject除了上面的两个函数,还有如下函数:
    • willReleaseChild/willReleaseChildren:释放某个对象,以及子对象(调willDealloc)
    • 关联对象:viewStack
    • 关联对象:parentPtrs,在willReleaseChildren会对已经处理过的对象进行添加,这样在assertNotDealloc中,会判断当前对象是否与父节点集合有交集
    • 白名单:classNamesInWhiteList

MLeakedObjectProxy

  • 前面assertNotDealloc已经两度提及该类的方法
  • isAnyObjectLeakedAtPtrs:
  • addLeakedObject:
    • 构造MLeakedObjectProxy对象
    • object强持有proxy,proxy若持有object。如果object释放,proxy也会释放
    • 弹窗提示
    • dealloc
      • 析构函数,弹窗提示前面的内存泄露对象在某个时间点重新释放了

willDealloc的执行时机:寻找释放点

  • 其调用是在第一步swizzle里面,swizzle了UIViewController,UIApplication,UINavigationController、UITouch的方法,hook后的方法里调用的(本质上就是在认为该释放的地方调用,寻找释放点)
  • 其实各种代码看到最后,MLeaksFinder检测的就是跟VC相关的代码,核心代码在VC里swizzle

UIViewController+MemoryLeak

  • 模态视图hook -> dismissViewControllerAnimated:completion:
    • 对将要dismiss的VC调willDealloc
  • navigationController被pop出来
    • hook navigationController的方法UINavigationController+MemoryLeak
      • popViewControllerAnimated
        • 代码截图省略了,splitViewController相关的代码
        • 上面并不是直接调willDealloc,而是设置了VC的一个关联参数属性kHasBeenPoppedKey为YES,因为用过左滑时间超过2s不放开,VC是不会释放的,因此此处通过关联对象处理
        • 如果VC出栈且释放,hookVC的viewDidDisappear,如果该关联参数为YES就调willDealloc
        • 如果滑到一半回来,hookVC的viewWillAppear,设置该关联参数为NO
      • popToViewController:animated:
      • popToRootViewControllerAnimated:
        • 后两种方法,系统方法调用是会返回pop掉的数组的,hook掉,获取pop调的数组,遍历,对每个vc依次调willDealloc
    • navigationController也加了willDealloc,如果navigationController被释放,释放其viewControllers
  • VC除了hook dismiss还hook了viewDidDisappear,viewWillAppear
    • 这两个方法前面都提到了,以及里面做了什么事情
  • willDealloc
    • 调Super,NSObject的willDealloc,前面介绍了,判断白名单,进行延迟调断言
    • 释放子VC,presentedVC,以及子view
      • 释放子view时,view的willDealloc方法里,是会调[self willReleaseChildren:self.subviews];
      • 这样看完了,能够完整的创建view的堆栈,就是因为willDealloc里会继续调子对象的释放willDealloc

特殊情况

  • 有时候即使调了pop,dismiss,也不会被释放,比如单例。如果某个特别的对象不会被释放,开发者可以重写willDealloc,return NO
  • 部分系统的view是不会被释放的,需要建立白名单
  • MLeaksFinder支持手动扩展,通过MLCheck()宏来检测其他类型的对象的内存泄露,为传进来的对象建立View-ViewController stack信息
  • 结合FBRetainCycleDetector一起使用时:
    • 内存泄漏不一定是循环引用造成的
    • 有的循环引用 FBRetainCycleDetector 不一定能找出
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值