最近面试了一波有个内存泄漏的问题现在回顾一下首先概念我之前有点不明确吧面试的时候回答的有点含糊由于朋友内推去面试的也算蒙混过关了~内存溢出用户要求系统分配的内存空间超出了系统所能提供的范围称内存溢出内存泄露用户向系统申请内存new使用完后没有释放的情况delete导致了该块内存不能再被用户使用也不能被系统调用。我们常说的内存泄露指的是堆泄露内存越界使用已申请的内存时超出了内存的界限。栈溢出栈满时再做进栈必定产生空间溢出叫上溢栈空时再做退栈也产生空间溢出称为下溢。ps典型的在C语言中在分配数组时为其分配的长度是1024但往其中装入超过1024个数据时由于C语言不会对数组操作进行越界检查就会造成内存溢出错误。出现死循环或者是大量的递归调用在不断的压栈过程中造成栈容量超过1m而导致溢出。栈溢出解决方法方法一用栈把递归转换成非递归通常,一个函数在调用另一个函数之前,要作如下的事情:a)将实在参数,返回地址等信息传递给被调用函数保存; b)为被调用函数的局部变量分配存储区;c)将控制转移到被调函数的入口. 从被调用函数返回调用函数之前,也要做三件事情:a)保存被调函数的计算结果;b)释放被调函数的数据区;c)依照被调函数保存的返回地址将控制转移到调用函数.所有的这些,不论是变量还是地址,本质上来说都是数据,都是保存在系统所分配的栈中的. 那么自己就可以写一个栈来存储必要的数据以减少系统负担。方法二使用static对象替代nonstatic局部对象在递归函数设计中可以使用static对象替代nonstatic局部对象即栈对象这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销而且static对象还可以保存递归调用的中间状态并且可为各个调用层所访问。方法三增大堆栈大小值当创建一个线程的堆栈时系统将会保留一个链接程序的/STACK开关指明的地址空间区域。但是当调用CreateThread或_beginthreadex函数时可以重载原先提交的内存数量。这两个函数都有一个参数可以用来重载原先提交给堆栈的地址空间的内存数量。如果设定这个参数为0那么系统将使用/STACK开关指明的已提交的堆栈大小值。后面将假定我们使用默认的堆栈大小值即1MB的保留区域每次提交一个页面的内存。之后回归主题再说一下iOS内存泄漏的常见情况1.声明delegate为strong类型简而言之如果父VC持有子VC并设置子VC的delegate为self也就是父VC这样的结果就是子VC也间接持有了父VC造成循环引用在Pop子VC的时候不会调用delloc。2.timer是否持有self我们一般要执行一个timer的时候会用(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo 这里的aTarget一般是self这时候就需要注意了如果在你退出的时候这个timer还在执行的话由于这个timer会持有self所以delloc也不会调用这里可以用weakSelf代替self也是没有问题的。3.最常见的就是block导致的循环引用由于在重构APP中用到了MVVM架构使用了大量的信号机制导致block到处飞哈哈解决的最多的就是这种了解决方法也很简单就是在block外声明__weak type(self) weakSelf self在block中用weakSelf就可以了还有就是在block中如果使用了成员变量的下划线形式也要改成weakSelf.PropertyName的形式。MVVM中定义了宏对weakify(self)和strongify(self)可以理解为__weak type(self) weakSelf self的简化形式可以拿来直接使用。3.图片没释放instrument调试后发现没被释放的全是imageIO差不多就知道了把读图的方式从[UIImage imageNamed:],改成imageWithContentsOfFile就可以了。4.使用GPUImage处理拍照的时候内存稳定不明增长。是Xcode7.1的问题。。只在debug的时候导致内存崩溃release的时候并不会造成内存溢出所以可以不必管它。5.CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
