2009-03-05 56 views
14

我正在寻找主要来源(或非常好的解释)来备份使用autorelease在为iPhone编写软件时危险或过于昂贵的说法。为什么autorelease对iPhone应用程序特别危险/昂贵?

有几位开发者提出这种说法,我甚至听说苹果公司不推荐它,但我还没有能够提供任何具体的资源来支持它。

SO引用:
autorelease-iphone
Why does this create a memory leak (iPhone)?

注:我可以看到,从概念的角度来看,这autorelease稍微比简单的调用release更贵,但我不认为小小的罚款足以让苹果推荐它。

什么是真实故事?

回答

11

(?不能接受你自己的答案)

嘛,毕竟,我还是设法找到从苹果开发者参考,加入靠近页面底部的侧面说明:

iPhone OS注意:由于在iPhone OS 应用在更 存储受限环境中执行,所述 使用自动释放池的不鼓励在 码方法或块 (例如,环),其中一个 应用CREA测试许多对象。 相反,您应该尽可能明确地发布 对象。

不过,这建议仔细使用autorelease,而不是完全避免它。

(现在对于我的评论)

听起来好像有在保持池开销一定的数量。我读this article这会导致我尽可能地避免autorelease,因为我更喜欢事情是一致的。如果你在autorelease下有一些内存,而其他内存是完全手动管理的,它可能会有点混乱。

+0

高兴地帮助(给我一些东西来搜索:-) – TofuBeer 2009-03-05 05:58:00

+1

他们没有提到的是很多基金会的调用autorelease对他们管理的对象,因此在紧密的循环中,你需要创建和管理你的类如果您正在处理适量的数据,则拥有自己的自动释放池。 – rpetrich 2009-03-05 07:06:43

0

我强烈建议避免像瘟疫一样自动释放。内存管理错误是浪费大量时间和金钱的好方法,我曾经在旧的Mac应用程序中经历过很多次这个过程的可疑荣誉,而且iPhone紧张的内存限制意味着你有要非常小心,否则应用程序就会不稳定并经常崩溃......就像去年夏天发布的许多第一批应用程序一样。

我发现编写稳定的iPhone应用程序的唯一可靠方法就是自己管理所有的内存,并且一致地执行。即使你是你项目中唯一的程序员,你以后也会感谢你。如果你学会了用“为你照顾所有东西”的语言进行编程,可能会很困难,但如果你对创建高质量的iPhone应用程序很认真,那么确实值得学习。

5

我不同意那完全避免autorelease是明智的。

Cocoa Touch在内部非常频繁地使用它,在很多情况下它是正确分配内存的唯一方式(一个很好的例子是可重用的表格视图单元格)。如果你明白发生了什么,autorelease池是一个很好的工具,可供您使用。要记住的主要问题是,在运行循环稍后的某个点之前,块才会被释放。如果你在没有用户交互的情况下运行一个紧密的循环,并且正在堆砌自动释放块,那么最终会导致内存不足。

Autorelease不是垃圾收集的替代品(在iPhone SDK中不可用),并且可能导致令人讨厌的悬挂指针错误(指针看起来仍然不错,然后在某个不可预知的地方变得无效),但也是在编写清晰易用的代码时非常有用。考虑以下情况:

[aDictionary writeToFile: 
    [documentsDirectory stringByAppendingPathComponent:@"settings.plist"] 
       atomically:YES]; 

路径字符串是作为autorelease对象生成的。我们不需要创建一个临时对象,所以我们避免了这种开销(我们可能会忘记释放它)。内存将被完全释放(不泄漏),只是它会在运行循环中稍后发生。问问自己:在我回到用户输入之前,我会分配数百个这样的数据吗?如果不是(就像这里的情况那样),autorelease是一个很好的解决方案,事实上,这个用于处理路径的NSString方法只能使用自动释放内存。

我同意上面的海报,遵循惯例和一致是一个非常好的主意。

4

我倾向于避免在iPhone上使用autorelease(正如Jon指出的,如果没有它,你总是不能这么做),只是因为我想知道我正在使用的对象是即时发布的我不需要他们。内存限制是你在设备上面临的最大问题之一,我相信它们是你在那里发现的大部分崩溃问题的根源。

正如Apple强调的那样,当您在任何类型的循环中使用自动释放对象时,特别关心的一个问题是,它们会堆积在自动释放池中。然后,您必须管理何时耗尽游泳池或创建/释放游泳池。这样做每次通过循环都可能会降低性能,但如果过多则不会导致危险的内存使用情况。我仍然在Molecules中对此进行了调整,因为从Protein Data Bank导入大量(> 2 MB)文本文件时存在间歇性内存问题。我能够通过减少自动释放对象来提高性能,但无法完全消除它们。

另一个需要注意的地方是使用带线程的自动释放对象。如果可能的话,在处理在后台线程上执行的方法时不要使用自动释放对象,因为该池可以随机抽取。这会导致间歇性崩溃,这可能非常有趣追踪。

9

这不是使用或不使用autorelease的问题,因为在某些情况下,autorelease是唯一的方式,你会通过。问题应该是“为什么不在所有对象上使用autorelease,而不是使用保留和释放?”。

要回答这个问题,你应该先了解一下autorelease的正确用法。假设您有一个具有两个属性的类:firstName和lastName。每个都有一个getter和一个setter。但你也需要,将返回全名,由这两个字符串连接成一个全新的字符串的方法:

- (NSString *) fullName { 
    NSString str = [[NSString alloc]initWithFormat:@"%@ %@", firstName, lastName]; 
    // this is not good until we put [str autorelease]; 
    return str; 
} 

什么是错的画面?返回字符串的引用计数为1,所以如果你不想泄漏,调用者应该在他完成时释放它。从来电者的角度来看,他只是要求物业价值fullName。他没有意识到他得到了一个全新的对象,他应该在使用后释放它,而不是对该类内部持有的NSString的引用!

如果我们在返回之前放置[str release],字符串将被销毁,并且该方法将返回垃圾!这是我们使用[str autorelease]的地方,以便稍后标记对象以便发布(通常在事件处理完成时)。这样调用者可以获得他的对象,并且不必担心他是否应该释放它。

约定是在方法将其返回给调用方之前,在新对象上调用autorelease。例外情况是名称以alloc,newcopy开头的方法。在这种情况下,呼叫者知道为他们创建了一个全新的对象,他们有义务调用该对象的释放。

完全用autorelease替换release是一个坏主意,因为对象会很快堆积并堵塞内存,特别是在循环中。 iPhone上的资源是有限的,所以为了最大限度地减少内存占用,完成它之后立即释放对象是您的职责。

相关问题