iOS调试内存泄露

[TOC]

Xcode8使用Memory Graph

  • 第一步:真机下运行APP后,点击


    image.png
  • 第二步:查看issue面板,注意选择右边Runtime


    image.png
  • 第三步:查看可能出现的内存泄露
    比如上图的 1 instance of __NSMallocBlock_leaked,点击后出现下图

    image.png

    原因在于如下代码

group.didSelectedRowBlock = { [unowned self, group] row in
   guard let indexPaths = group.selectedIndexPaths else {return}
   if indexPaths.count > 0 {
       self.shouldAdd = true
       let row = (indexPaths.firstObject as! IndexPath).row
       self.deviceAttri?.attrValue = String(row)
   } else {
       self.shouldAdd = false
   }
}

group的block中又使用了group,导致了循环引用,虽然使用了[unowned group],事实证明并没有效果
最后的解决办法是修改didSelectedRowBlock的接口,直接将selectedIndexPaths参数传入block参数中:

group.didSelectedRowBlock = { [unowned self] indexPaths in
    guard let indexPaths = indexPaths else {return}
    if indexPaths.count > 0 {
        self.shouldAdd = true
        self.deviceAttri?.attrValue = String(indexPaths.first!.row)
    } else {
        self.shouldAdd = false
    }
}
  • 第四步:在 debug 页面查看内存泄露情况


    image.png

    有叹号说明需要注意可能存在内存泄露,可以看到 CoreFoundation中也可能存在内存泄露情况

使用Instruments的Leaks工具

Time Profiler

  • 查看多个线程里那些方法费时过多的方法
  • Call Tree上会默认按照费时的线程进行排序,单个线程中会也会按照对应的费时方法排序


    image.png

Allocations

  • 可以对每个动作的前后进行Generations,对比内存的增加,查看使内存增加的具体的方法和代码所在位置
  • 具体操作
  1. 在右侧Generation Analysis里点击Mark Generation,这样会产生一个Generation,
  2. 切换到其他页面或一段时间产生了另外一个事件时再点Mark Generation来产生一个新的Generation,
  3. 这样反复,生成多个Generation,查看这几个Generation会看到Growth的大小,如果太大可以点进去查看相应占用较大的线程里右侧Heaviest Stack Trace里查看对应的代码块,然后进行相应的处理。

Leak

可以在上面区域的Leaks部分看到对应的时间点产生的溢出,选择后在下面区域的Statistics>Allocation Summary能够看到泄漏的对象,同样可以通过Stack Trace查看到具体对应的代码区域。

其他调试方法

勾选Address Sanitizer可以在运行时看到坏内存访问情况

image.png

你可能感兴趣的:(iOS调试内存泄露)