iOS 内存管理那些事

      最近在拉钩看到一个面试评论,有个哥们在优酷面完后评论--“ARC下有谁会用autorelease,问我autorelease后的对象何时释放,老子能知道?要是在流媒体开发中会用到它我脑袋削下来给你当板凳。”

      看完评论的我也陷入沉思,这似乎优点像以前的我---总在找别人的毛病,曾经的我一直觉得iOS开发哪需要什么算法,整天在写UI,顶多写个冒泡排序,面试算法多此一举。不过经过多轮的面试,心境早已变了,开始尝试着站在对方角度看问题,毕竟抱怨对自己没有一点助益,现在的我都开始啃《算法导论》《代码大全》。对那个兄弟,我只想说----停止抱怨,你会得到更多。作为一个iOS程序员(快满大街的职业),说自己会自动布局,会写tableview代理数据源,...,怎么能凸显出你的专业素养与逼格?我们需要打造自己的技术护城河,最近研究OpenGL ES也有些心得,过段时间可能写图像处理方面的blog.


      闲话不说了,步入正题,本文主要围绕MRC下内存管理概念及重要的注意点(这对于理解ARC内存管理也很有帮助,而且面试经常遇到)

本文中大部分内容来自Advanced Memory Management Programming Guide,有兴趣的可以自行参考文档,我也会在适当地方给出原文。

一.MRC下的内存管理(先简单回顾,重点在后面)

无论在MRC还是ARC下都是采用引用计数来管理内存,只不过在ARC下编译器在编译时为你自动插入了retain,release,autorelease等内存管理语句,当对象的引用计数为0时会被释放。

retain,release语句成对出现,retain引用计数+1,release引用计数-1.

基本的内存管理原则:

1.使用alloc,new, copy, mutablecopy创建的对象,你自动获得所有权,即引用计数加1.

2.要获得一个对象的所有权,使用retain.

3.当你不需要使用时,释放你拥有的对象,使用release,autorelease.

注意点:

1.autorelease的出现是为了实现返回对象的方法。(可能是原因之一吧)

- (NSString *)name {

          NSString *str = [[NSString alloc] initWithFormat:@"hello"];

//在MRC下,若不用autorelease,无法返回str,像这样,str将会泄漏。你必须想办法释放它。若直接释放,则在返回之前str就已经无效了。

         return str;

}

2.集合类对象自动对存入的对象进行retain,移除对象或者销毁集合本身时也会解除拥有关系,发送release。

3.不要使用dealloc方法管理稀缺资源。

什么稀缺资源?原文这样说--You should typically not manage scarce resources such as file descriptors, network connections, and buffers or caches in a dealloc method.

原因:dealloc可能会被推迟执行,甚至被绕过不执行。(什么时候会绕过呢,当app被结束时,系统不会挨个调用dealloc回收内存,这样比较低效,系统直接自己释放回收了app占用的内存。)

导致的严重问题:1.资源得不到正确释放,比如文件资源,那磁盘将会被占满,用户无法存储东西(If your application runs out of file descriptors, for example, the user may not be able to save data.)比内存泄漏严重多了,是不是需要清理磁盘或重装系统。

2.清理的逻辑在错误的线程执行。若对象在不恰当时间autorelease,它将在不确定的某个线程的自动释放池中销毁,对于有些资源要求只能在一个线程访问来说,后果是严重的。(If an object is autoreleased at an unexpected time, it will be deallocated on whatever thread’s autorelease pool block it happens to be in. This can easily be fatal for resources that should only be touched from one thread.)

面试中的那些问题

1.autorelease的对象什么时候释放?

在它所在的最内层自动释放池结束时,它会收到release消息释放。每一个线程都维护着属于自己的自动释放池栈。

2.什么样的对象会被放入自动释放池?

收到autorelease消息的对象,在ARC下,若不是用alloc, new,copy, mutablecopy创建的对象,一般可以认为系统自动添加了autorelease,所以会被放入自动释放池,而alloc等创建的不会放入,在ARC下若要尽早释放alloc等方法创建的对象,只需要赋值nil就好了。没有强引用就会自动释放。自动释放池只对接收了autorelease消息的对象有用。

3.多线程与自动释放池,新创建的线程需要创建释放池吗?

若使用NSThread创建的线程,需要创建释放池,否则会造成内存泄漏。默认只在主线程的运行循环中自动创建自动释放池,所以一般有关UI的操作,不需要手动创建自动释放池,在每一个循环结束时,释放池中的对象会被释放。(Each thread in a Cocoa application maintains its own stack of autorelease pool blocks. If you are writing a Foundation-only program or if you detach a thread, you need to create your own autorelease pool block.)

4.使用gcd 、OperationQueue等创建的线程需要创建释放池吗?

不需要,我在Concurrency Programming Guide中找到一段话,Although GCD dispatch queues have their own autorelease pools, they make no guarantees as to when those pools are drained. If your application is memory constrained, creating your own autorelease pool allows you to free up the memory for autoreleased objects at more regular intervals.

大致意思就是,gcd的队列有自己的自动释放池,但是不保证什么时候释放,如果你需要尽快释放内存,你可以在block中创建自己的自动释放池以便更频繁地释放。所以一般情况下不需要,除非你内存很吃紧,需要极力优化。因为OperationQueue等高层API是基于GCD的,所以可以大胆猜想,它必然也是有自己的自动释放池。

5.什么时候需要使用自动释放池?

官方给出的三中情形:

1.If you are writing a program that is not based on a UI framework, such as a command-line tool.(若写的程序无关UI,比如命令行程序,)

2.If you write a loop that creates many temporary objects.(在for循环中创建过多临时对象,可以用来尽早释放,避免内存峰值过高)

You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.

3.If you spawn a secondary thread.(你创建了第二个线程)

You must create your own autorelease pool block as soon as the thread begins executing; otherwise, your application will leak objects. (SeeAutorelease Pool Blocks and Threads blog for details.)你需要在线程开始执行时尽早创建自己的自动释放池,否则你的应用将会内存泄漏。


最后:第一次写总结,难免有纰漏,若大家发现有问题,希望及时指正。

抛出一个问题:Don’t Use Accessor Methods in Initializer Methods and dealloc,文档中这句有没理解,为什么在MRC下不允许在init和dealloc中使用属性访问方法而是直接使用实例变量?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容