1)内存的问题是发现越早,解决的代价就越小。所以最重要的是理解Objective
C内存管理,遵循我之前提到的实践准则和编码规范。另外,在每个迭代周期要做一些压力和内存测试,尽早发现问题。
2)利用Clang静态检测工具。在XCode 3.2之后的版本里,Clang已经被集成进来。Build ->Build & Analyze即可运行,它可以发现大部分因为疏忽造成的内存泄露。比如有Alloc没有release等。下图是一次静态检测的结果. 如图所示,Clang清楚的告诉你在145行有潜在的内存泄露,即label有alloc没有release。
图一 Clang静态检测
3) 如果静态检测工具不能解决问题,就需要更多的分析和借助instruments工具。
a)首先要重现问题,找到是哪些操作容易产生内存泄露。主要通过一些测试和推理来判断,比如找出哪些操作重复进行时,内存增长比较明显或者会Crash。
b)借助instruments工具。instruments是在程序运行时在程序中注入一些代码来动态的检测内存分配状况和泄露问题。Run -> Run with perfomance tools - > leaks 即可启动。下图是运行leak instrument的一次结果,如果leak是你的代码引起的,你还可以直接查看到引起泄露的代码。
图二 leaked Blocks
图三 leaked code
c)还有一个instrument叫Allocation,它可以实时监测当前分配了多少内存。结合这个来进行a)步骤的推断,往往会比较有效。可以通过Run -> Run with perfomance tools - >Allocations启动,也可以在instruments启动后通过window->library ->Allocations加进来。
4)可以找你的同事codereview,旁观者往往能发现问题。有时候内存泄露是一些理解上的误区造成的。比如我以前一直以为
-viewDidUnload是在这个View被unload之后调用,所以我在里面做一些清理工作,比如Remove
EventHandler等, 后来才知道这个函数是在内存不足需要unload view时才被调用,这个理解误区导致我花了一周的时间解决一个内存泄露的bug。 还有一个例子,之前我的一个同事一直以为[NSDate new]是产生当前时间,并不需要释放,这也是一个比较低级的理解误区。
5)有些内存问题可能是缓存引起的,并不一定是泄露。比如在Three20(Facebook IPhone Library)里,出于性能的考虑,默认会在内存里cache一些网络图片. [UIImage imageNamed:]也会把图片放到system cache里面,这不能算是泄露,但有时候会引起内存不足。
黄锦
Email: hj@s-tuan.com
关注移动互联网,电子商务