一、导致内存泄漏发生的常见原因:
1. 循环引用(见前篇文章)
2. 死循环
如果某个ViewController中有无限循环,也会导致即使ViewController对应的view关掉了,ViewController也不能被释放。
这种问题常发生于animation处理。比如:
CATransition *transition = [CATransition animation];
transition.duration = 0.5;
tansition.repeatCount = HUGE_VALL;
[self.view.layer addAnimation:transition forKey:"myAnimation"];
上例中,animation重复次数设成HUGE_VALL,一个很大的数值,基本上等于无限循环了。
解决办法是,在ViewController关掉的时候,停止这个animation。
-(void)viewWillDisappear:(BOOL)animated {
[self.view.layer removeAllAnimations];
}
3. 有时候需要用removeFromSuperView
来释放:
具体说明,也许a对象拥有一个b对象,b对象add到了c对象上,而在设计中b对象的生命周期应该和a对象相同;这时候只一句[b release]/self.b = nil是不能把b对象释放掉的(一般情况下release会使其retainCount-1,[super dealloc]会再次将所有subView的retainCount-1,而b并不是a的subView,所有最后的一次-1没有了);所以需要在之前加上[b removeFromSuperView]。
4. 图片没释放
instrument调试后,发现没被释放的全是imageIO。解决方法:把读图的方式,从[UIImage imageNamed:@”“],改成imageWithContentsOfFile。
5. CoreFoundation对象(C对象):
只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
二、检查内存泄漏的方法:
1. 使用Xcode自带的leaks动态检查内存泄漏:
选择Xcode -> Open Developer Tool -> Instruments -> Leaks工具
2. 使用代码(重写dealloc方法)
Leaks工具虽然强大,但是它不能检测到block循环引用导致的内存泄漏,这种情况一般需要自行排查问题,傻瓜式的方案当然是重写对象的dealloc方法
来监测对象是否正常释放,来确认没有形成循环引用。
内存访问验证的原理:许多这类工具在运行时验证内存访问的有效性,从而查找到问题。理论依据是:访问内存时,通过比较访问的内存和程序实际分配的内存,验证内存访问的有效性,从而在bug发生时就检测到它们,而不会等到副作用产生时才有所察觉。