在没有 NSAutoReleasePool 的情况下使用 autoReleased 对象?

Posted

技术标签:

【中文标题】在没有 NSAutoReleasePool 的情况下使用 autoReleased 对象?【英文标题】:Using autoReleased objects without an NSAutoReleasePool? 【发布时间】:2011-06-22 22:01:59 【问题描述】:

我正在用 Objective-C 编写我的第一步。 我遵循了一些示例和官方文档,并使用了自动释放的对象*,而没有明确声明 NSAutoReleasePool。

* 我的意思是自动释放的对象:SomeClass *obj = [SomeClass someClass];

这样可以吗? 会不会导致内存问题? 声明 NSAutoReleasePool 是否更有效?

编辑:我在代码示例中犯了一个错误,我的意思是通过它的类工厂方法而不是allocing 它的实例来获取一个对象。这个工厂方法[经常|总是]返回自动释放的对象,对吧?例如:[NSString stringWithCString:x]

【问题讨论】:

当心那些说某些方法返回自动释放对象的文本(包括许多关于 Stack Overflow 的帖子)。有时他们会,有时他们不会。将它们视为返回不属于调用者的对象的方法会更加准确和高效。 对。所以,在调用范围内使用它们是安全的,除此之外,它应该是retained,对吧? 【参考方案1】:

您通常不需要显式创建自动释放池。当您使用 AppKit 框架进行正常的 Mac 编程时,将有一个由事件循环处理的隐式自动释放池。您主要需要在两种情况下关注自动释放池:

您的代码在后台线程中运行:如果您有后台线程,则没有为您创建自动释放池,您必须手动执行此操作。 您有一个紧密的循环,您可以在其中创建和销毁大量对象。如果在这个循环中任何对象被自动释放,它们实际上不会被释放,直到自动释放池被耗尽。这意味着即使您不再引用这些对象,您的内存消耗也会增加。在这种情况下,拥有本地自动释放池有助于提高性能,尽管从自动释放切换到显式保留/释放可能更有效。

【讨论】:

对不起,我的意思不是字面上的 Class,但是 someClass 会更正它。 应用程序对象在每个事件中创建和排出自动释放池,而不是运行循环。如果你只创建一个运行循环,而不是一个应用程序对象,你仍然需要创建和耗尽你自己的池。【参考方案2】:

在回答您的问题时:这是不可以的。如果您在没有自动释放池的范围内自动释放对象(或使用自动释放的对象),则会发生内存泄漏。

也许忽略以下内容:

关于您的示例,您编写它的方式可能相当混乱,因为Classstruct objc_class* 的typedef。因此,您实际上是在声明指向类的指针,然后将指向类的指针分配给它。这是行不通的。此外,由于Class 本身不是Objective-C“类类型”,因此您不能向它发送消息。 但这一切都不存在,因为±class 不返回自动释放的对象。

【讨论】:

我怀疑 Petruza 正在一个普通的 Cocoa 应用程序的主线程上工作,所以自动有一个自动释放池,不显式创建一个自动释放池是完全可以的。只有在辅助线程和需要优化的情况下才需要处理自动释放池(请参阅下面的 frenetisch applaudierend 的答案)。正如您所解释的,Class *obj = [Class class]; 代码仍然没有意义。 对不起,我的意思不是字面上的Class,而是someClass,会更正它。 @puzzle 是的,你完全正确。在您会遇到的大多数情况下,肯定会有一个活动的自动释放池。但是main+load 等中不会自动拥有一个。

以上是关于在没有 NSAutoReleasePool 的情况下使用 autoReleased 对象?的主要内容,如果未能解决你的问题,请参考以下文章

Instruments 中的 NSAutoreleasePool 泄漏

目标 C - NSthread 和 NSAutoreleasePool?

NSRunLoop 和 NSAutoreleasePool,它们是如何交互的?

NSAutoReleasePool 泄漏

如何在 AppleScriptObjC 中使用 NSAutoreleasePool

了解 NSAutoreleasePool