iOS 6的闪退和内存教程

原文:http://blog.csdn.net/javayujiafeng/article/details/8445007

先说闪退是什么,闪退就是程序崩溃了,原因多种多样,内存不足是一种,大部分是因为程序本身有BUG(BUG中野指针类居多,建议百度下野指针,能看懂的就看懂了,看不懂的就不解释了,几句话说不清楚)

讲一个概念,虚拟内存。咱从windows说起,让大家好理解。在windows上,如果你电脑有1G内存,但是你的程序需要2G内存才能跑,那这个程序会崩溃掉么?答案是一般不会。windows有虚拟内存机制,大概的意思是,用硬盘去扩充内存。硬盘和内存本质都是存数据嘛,无非内存快,硬盘慢,如果一个程序需要的内存多到要用上虚拟内存,那么也只会变慢,但是不会崩溃掉。这个技术很好是么,iOS有没有呢,sorry,没有

好,这里讲讲为什么去掉了虚拟内存机制。手机和电脑一个很大的区别是,电脑上同时运行许多程序的需求很大,比如我现在就一边听音乐,一边还开着QQ,一边还开着浏览器,因为屏幕大呀,可以同时放下好多程序的窗口。有了虚拟内存,windows可以同时运行很多程序,万一内存不够用,就用虚拟内存顶上,至少各个程序只是性能变差,但是不会崩溃。除非你开非常多非常占内存的程序,需要的内存超过了内存和虚拟内存的总和,系统才会被迫让一些程序终止,这种情况还是很少见的,但是理论上是可能的。但是,手机屏幕只有那么点点大,往往只能显示一个程序的窗口,加上虚拟内存会显著降低性能,iOS索性取消掉了多个程序同时执行的能力,也取消掉了虚拟内存。用户看上去可能觉得不是这样,比如音乐播放程序是可以后台执行的,QQ看上去也在执行,还能收消息呢,其实这些都是假象,如果这帖子大家反馈不错的话,我再讲iOS的假后台吧。

OK,以上内容我们得到两个结论:1.iOS没有虚拟内存,在4s上能使用的内存就只有512M;2.没有后台能力,在用户按下HOME之后,程序就不执行了。我们从这两个结论和对比windows开始讲讲iOS内存如何管理的。先不考虑多程序运行,看看windows,假如我们打开QQ,QQ开始执行,占用一部分内存,QQ执行结束,这部分内存归还给操作系统;如果我们只是把QQ最小化,QQ还是会霸占着这部分内存,除非我们关闭QQ,内存才会归还给系统,so简单so容易理解,对么?来看看iOS,iOS不一样哦,一个程序被按了HOME之后,很像是最小化了对么,事实上它已经不执行了,但是是暂停状态而不是终止掉,当你再次点击QQ,QQ会回到屏幕上继续执行。而且在iOS上,一个被最小化的程序的内存是有可能随时被系统要回去的哦,这点和windows完全不一样,windows不会找程序要的,只有程序关闭后主动还给系统的。还有个很大的不同是,windows上的QQ什么时候终止运行是固定的,就是用户关闭QQ的时候;iOS又不一样了,因为iOS只有相当于最小化的HOME,那么QQ什么时候终止运行呢?当QQ被最小化,暂停了,而且正在运行的程序内存不够用的时候,系统会主动终止QQ,并要回QQ占用的内存,给正在运行的程序用。那么iOS上,一个没有BUG的程序(事实上世界上根本没有没有BUG的程序啦,这里假设有)什么时候会因为内存不够退出呢?答案是当系统释放掉所有最小化的程序,把所有内存都给这个正在运行的程序,但是它还是不够用,系统才会干掉它,它就闪退了(其实这个也蛮理想化的,没这么绝对,往往有内存泄漏的程序,占用内存的速度会超过系统给他分配内存的速度,而且从某种意义上说,即使这个程序不是内存漏了,而是就是需要这么多内存,这种也应该算广义的BUG了,是程序猿压根没设计好,PS:如果这个括号和上一个括号反而让你感觉无法理解的话,忽略这两个括号吧)。

有了前一楼的概念,我们大概知道了内存如何管理的。那么最近在iOS 6上因为内存不足而闪退的程序变多是为什么呢?咱们先来思考一个简单的问题。假设一个程序猿要写一个程序,这个程序需要的内存比较多,有可能超过系统的限制,注意只是可能,怎么办呢?我给出两种解决方案:1.这个程序时时刻刻关注自己用了多少内存,一旦要超过限制了,释放内存;2.这个程序只管用,系统在这个程序要用的内存快超过限制的时候告诉这个程序“你快爆炸了”,这时候程序去释放一些内存。哪种方便呢?我和绝大多数程序猿都选的第二种。第一种难度很大,虽然系统会尽力给程序最多的内存,但是系统回收内存也是要时间的,可能系统还没来得及给,程序就已经爆炸了,这个很难掌握,一个程序不可能知道有多少程序被最小化了,也不可能在一个具体的时间点上知道自己到底能用多少内存,还是等系统通知来的方便。

那么理论上,只要系统告诉程序,你要爆炸了,程序释放内存,一切安好。理论是这样的,但是细节上总不能保证你若安好便是晴天。iOS 3-5用的相同的方式告诉程序,你要爆炸了,iOS 6也会告诉,但是方式变了一点点,具体我写在最后,让有点程序设计知识的封釉看看。打个形象的比方,iOS 3-5会说,你要爆炸了。iOS 6开始说英语了,you gonna bomb,没及时更新的程序只懂中文不懂英语,没鸟系统,然后自己就真的爆炸了,闪退了。所以开篇我说,手动清理下内存可能有点用,但是用处不是很大,因为你可以尽量多提前清理出内存给程序用,程序内存不足的概率就降低了。可惜程序就是不鸟系统的话,运行时间长了还是会挂掉;而且,iOS 6细枝末节的更新很多,其他方面也可能引起BUG闪退,不过确实内存方面的原因占了绝大多数。真正的终极解决办法是,写程序的程序猿更新版本,让程序既可以听懂iOS 3-5的你要爆炸了,也能听懂iOS 6的you gonna bomb,才能让程序不再闪退,稳定运行。大部分程序猿都在努力更新中。用户们,可能只能先凑合下了,手动清理下,或许有效,只是或许。

好了,以上真正的原因我也讲完了,我尽可能简单通俗,希望能给大家带来点新姿势,咳咳,知识。最后写点编程方面的东西,没有编程知识的封釉可以评个分然后看其他帖子了。




iOS 3-5中,清理内存用的viewWillUnload和viewDidUnload,iOS 6开始系统不调用了,真心很操蛋呀,系统只调用那个什么receiveLowMemoryWarning了。有个解决办法,viewWillUnload和viewDidUnload可以不改,在receiveLowMemoryWarning里面,判断下系统版本,如果大于5,那么手动调一把viewWillUnload,然后自己干掉界面,self.view = nil;然后再调一把viewDidUnload,OK,下次进这个界面时候loadView和viewDidLoad还是会调用,又和iOS 3-5一样了,哇哈哈哈哈

相关推荐