一,内存泄露和内存溢出
- 内存泄漏(memory leak):是指申请的内存空间使用完毕之后未回收。
- 一次内存泄露危害可以忽略,但若一直泄漏,无论有多少内存,迟早都会被占用光,最终导致程序crash。(因此,开发中我们要尽量避免内存泄漏的出现)
- 供应方(操作系统)能提供给需求方(App)的内存越来越少。
- 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用。
- 通俗理解就是内存不够用了,通常在运行大型应用或游戏时,应用或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。最终导致机器重启或者程序crash。
- 需求方(App)需要的内存过大,超过供应方(操作系统)负载。
二,内存泄露的危害
- 从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到
三,内存泄露的检查方法
- MLeaksFinder框架检查内存泄露,弹框显示
- 点击调试窗口的Debug Memory Graph,查看引用路径
- 静态检查:product -》analyse
- 动态检查:product-》profile
- 开启僵尸对象检查:如果出现EXC_BAD_ACCESS,启用NSZombieEnabled(edit Scheme -》Diagnostises -》勾选Zombi Object)
四,常见内存泄露的原因及解决办法
- block的引用
- 修饰self:block外部弱化__weak type(self) weakSelf = self,block外部强化__strong typeof(weakSelf) strongSelf = weakSelf;
- 修饰变量:没有_ _block修饰是传值,作为常数使用;有修饰是传地址,作为变量使用,可以改变
- delegate被强引用,应该改成weak修饰
- 控件被strong修饰,应该改成weak修饰
- NSTimer未销毁,self作为target;应该改成weakSelf
- [UIImage imageNamed:@”“]引用大的图片文件;应该改成改成imageWithContentsOfFile
- 大循环未来的及释放,需要自己建autoReleasePool释放池
- 通知和KVO未移除
- CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
- NSUrlSession产生的内存泄露:delegate为retain,session使用完后置空
- UIWebView产生的内存泄露:shouldStartLoadWithRequest代理方法中,有可能URL有重定向,需要判断request的url是否为空,再往下执行NSURLSession的dataTaskWithRequest方法,进行文件的下载