iOS 使用Instruments工具检查内存泄漏问题
内存泄漏,通俗来说就是有一块内存区域被你占用了,但你又不使用这块区域也不让别人用,造成内存浪费,这就是内存泄漏,泄漏严重会造成内存吃紧,严重的会使程序崩溃。
在ARC内存管理模式下,产生内存泄露的的情况如下:
- retain cycle,block强引用
- delegate循环引用问题
- 定时器NSTimer释放不当
- 第三方提供方法造成的内存泄漏
- CoreFoundation方式申请的内存,忘记释放
一、使用Instruments的Leaks工具进行内存泄露的检测
demo在最下面给出
打开Xcode
自带的Instruments
方法一:
方法二:
或者:下图
build
成功后自动跳出Instruments
工具,选择Leaks
选项即可打开Instruments
方法三:
或者:长按运行按钮,然后出现如图所示列表,点击
Profile
打开Instruments
在下面的
Instruments
列表中选择Leaks
Instruments
以上算是打开Instruments
的基本方法,下面开始进行使用Instruments
进行内存泄漏检测
-
首先编译代码,上面的方法二,快捷键(
Leakscommand+i
),编译完成弹出Instruments
选择Leaks
-
点击上面开始运行项目,这时候会启动app
启动app -
对于启动的项目,点击按钮push到第二个界面,再次pop回来,反复几次,为了内存泄漏更明显一点
app界面1
app界面2 -
接下来会发现出现红色的x,这个就表示出现了内存泄漏
Leaks -
在下面的模式中切换到
Call TreeCall Tree
模式下,可以看到列表里列出了内存泄露的调用逻辑:
-
下面就是
Leaks选项最关键
的一步,在这个界面的下面有若干选框,在Call Tree
选项中选中Separate by Thread
和Hide system Libraries
Separate By Thread:线程分离,只有这样才能在调用路径中能够清晰看到占用CPU最大的线程。每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的"重"线程,按线程分开做分析,这样更容易揪出那些吃资源的问题线程。特别是对于主线程,它要处理和渲染所有的接口数据,一旦受到阻塞,程序必然卡顿或停止响应。
Invert Call Tree:从上到下跟踪堆栈信息.这个选项可以快捷的看到方法调用路径最深方法占用CPU耗时(这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法),比如FuncA{FunB{FunC}},勾选后堆栈以C->B->A把调用层级最深的C显示最外面.反向输出调用树。把调用层级最深的方法显示在最上面,更容易找到最耗时的操作。
Hide System Libraries:表示隐藏系统的函数,调用这个就更有用了,勾选后耗时调用路径只会显示app耗时的代码,性能分析普遍我们都比较关系自己代码的耗时而不是系统的。基本是必选项。注意有些代码耗时也会纳入系统层级,可以进行勾选前后前后对执行路径进行比对会非常有用.因为通常你只关心cpu花在自己代码上的时间不是系统上的,隐藏系统库文件。过滤掉各种系统调用,只显示自己的代码调用。隐藏缺失符号。如果 dSYM 文件或其他系统架构缺失,列表中会出现很多奇怪的十六进制的数值,用此选项把这些干扰元素屏蔽掉,让列表回归清爽。
Flatten Recursion:递归函数, 每个堆栈跟踪一个条目,拼合递归。将同一递归函数产生的多条堆栈(因为递归函数会调用自己)合并为一条。
-
选中显示的若干条中的一条,双击,会自动跳到内存泄露代码处,如图所示:
泄漏提示
双击后显示如下:
问题代码 -
接下来就可以修改问题代码来解决内存泄漏问题
注意
在选择
注意点Call Tree
后,可能你会发现查看不到源码从而无法定位内存泄漏的位置,只是显示16进制的数据。此时需要你在Xcode中检查是否有dSYM File生成,如下图所示选择第二项DWARF with dSYM File。