为啥我的自动释放对象没有被释放?
Posted
技术标签:
【中文标题】为啥我的自动释放对象没有被释放?【英文标题】:Why isn’t my autoreleased object getting released?为什么我的自动释放对象没有被释放? 【发布时间】:2011-02-25 19:58:51 【问题描述】:我正在调试一个奇怪的内存管理错误,但我无法弄清楚。我注意到我的一些对象在内存中的停留时间比预期的要长。我检查了我所有的内存管理,最后得出了一个非常不可能的结论,即我的一些autorelease
操作不会导致release
。在什么情况下可能?我创建了一个小型测试 Canary
类,它在 dealloc
中记录一条消息,并有以下测试代码:
NSLog(@"On the main thread: %i.", [NSThread isMainThread]);
[[[Canary alloc] init] autorelease];
根据代码,我们确实在主线程上,但 Canary
中的 dealloc
直到很久以后才会被调用。延迟不是确定性的,很容易花费几秒钟或更长时间。这怎么可能?应用程序在 Mac 上运行,垃圾收集已关闭(Objective-C Garbage Collection 在目标上设置为 Unsupported。)我主要习惯于 ios,是OS X 上的内存管理在某些重要方面有何不同?
【问题讨论】:
Mac OS X下的内存管理不同之处在于可以使用GC。如果您不选择 GC,那么不,没有什么不同。 【参考方案1】:autorelease
没有按预期运行的唯一情况是当前线程上没有自动释放池。只有少数情况会发生这种情况,如果发生这种情况,您会在控制台上打印出非常响亮的日志消息。如果您没有看到该日志,则 autorelease
的行为正常。更有可能的是,您的代码中的某些内容在此 Canary 对象上调用 retain
,然后从未释放它。
【讨论】:
我确定我没有保留测试对象,我实际上是在做[[[Canary alloc] init] autorelease]
,甚至没有使用返回值。我发现autorelease
确实会在一段时间后被调用,但延迟很大。我认为我的问题与运行循环行为有关,我将在明天添加更多信息。
autorelease
会立即被调用。零延迟。它的作用是稍后致电release
。这通常发生在控制传递回运行循环时。
对不起,我没有表达清楚。我的意思是自动释放池中的release
被延迟了。【参考方案2】:
自动释放的对象在其池耗尽之前不会被释放。因此,如果您使用自动释放缓冲区循环遍历图像,则最好在每次循环时创建和排出一个池。
【讨论】:
如果你在每次循环中只创建几个对象,你不想每次都创建一个自动释放池。如果您创建 10 个或更多,那很好。此外,如果您的循环不是特别长,那么就没有真正需要自动释放池。如果您正在运行数百次重循环或数千次轻循环,那么您可能需要一个。 另外,如果您将它自动释放到应用程序的池中,它不会被释放(池不会被耗尽),直到应用程序处理一个事件。正如我们在 Growl 中发现的那样,这使得后台应用程序中的内存管理变得棘手。如果您将对象自动释放到您在main
中创建的池中,然后运行应用程序,那么该池将永远不会耗尽,因为应用程序终止将首先退出进程。
@Peter:是的,我的应用程序在后台运行,这很可能是我的问题的根源。您可以将其作为答案提交吗?我也将不胜感激。【参考方案3】:
Mike Ash 有一篇名为 More Fun With Autorelease 的博文解释了这个问题的根源。引用:
众所周知,每次去 通过事件循环,可可吹 把旧水池拿走,换一个新水池 为你,让你的所有 自动释放的对象消失了,你的 新的进入一个新的池。那 永远不会建立更多对象的方式 比在单次生产 事件循环周期。关键词是“事件循环”。在 苹果的无限智慧,那些事 不是真正的实际 NSEvents 不是 触发池。
我目前正在开发一个应用程序 在后台花费大量时间 做黑暗的,无法形容的事情 主线程上的 NSStreams。一世 遇到了一个错误,我的一个 对象可以在 处理流事件的中间, 这让它可以得到其他 之后的流媒体事件 解除分配。 (…)
明显的解决方法是简单地做
[[self retain] autorelease]
之前 拨打问题电话。并修复它 做了,除了我的 dealloc 发生在我的活动中间 处理程序,它从未发生过。直到我点击了我的应用程序的停靠图标。
至少解决方案很简单。邮政 中的
NSApplicationDefined
事件 流事件处理程序,并自动释放 对象按计划销毁。
我发誓我必须从头到尾阅读博客,这是一个很好的时间投资。
【讨论】:
是的,就是这样。我们曾经在 Growl 中做一些更骇人听闻的事情,但这就是我们现在正在做的事情,而且效果很好。以上是关于为啥我的自动释放对象没有被释放?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Chrome Profiler 没有为我的对象显示正确的保留路径,为啥我的对象从未被释放?