为什么我的自动释放对象没有被释放?

发布于 2024-10-19 06:43:24 字数 566 浏览 2 评论 0原文

我正在调试一个奇怪的内存管理错误,但我无法弄清楚。我注意到我的一些对象在内存中停留的时间比预期的要长。我检查了所有内存管理,最后得出了一个非常不可能的结论:我的一些 autorelease 操作不会导致release。什么情况下可以呢?我创建了一个小型测试 Canary 类,该类在 dealloc 中记录一条消息,并具有以下测试代码:

NSLog(@"On the main thread: %i.", [NSThread isMainThread]);
[[[Canary alloc] init] autorelease];

根据代码,我们实际上位于主线程上,但是 Canary 中的 dealloc 直到很久以后才会被调用。延迟是不确定的,很容易需要几秒钟或更长时间。这怎么可能?应用程序在 Mac 上运行,垃圾收集已关闭(Objective-C 垃圾收集在目标上设置为不支持。)我主要习惯于 iOS,是OS X 上的内存管理在某些重要方面有所不同?

I am debugging a weird memory management error and I can’t figure it out. I noticed that some of my objects are staying in memory longer than expected. I checked all my memory management and finally got to the very improbable conclusion that some of my autorelease operations don’t result in a release. Under what circumstances is that possible? I created a small testing Canary class that logs a message in dealloc and have the following testing code in place:

NSLog(@"On the main thread: %i.", [NSThread isMainThread]);
[[[Canary alloc] init] autorelease];

According to the code we’re really on the main thread, but the dealloc in Canary does not get called until much later. The delay is not deterministic and can easily take seconds or more. How is that possible? The application runs on a Mac, the garbage collection is turned off (Objective-C Garbage Collection is set to Unsupported on the target.) I am mostly used to iOS, is memory management on OS X different in some important way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终难愈 2024-10-26 06:43:24

autorelease 无法按预期运行的唯一情况是当前线程上没有自动释放池。只有少数情况会发生这种情况,如果确实发生,您会在控制台上打印一条非常响亮的日志消息。如果您没有看到该日志,则 autorelease 的行为正常。更有可能的是,您的代码中的某些内容正在调用此 Canary 对象的 retain ,然后永远不会释放它。

The only circumstance in which autorelease does not behave as expected is when there is no autorelease pool on the current thread. There are only a few situations where you can expect this to occur, and if it does, you get a very loud log message printed to the console. If you're not seeing that log, then autorelease is behaving appropriately. Far more likely is the fact that something on your code is calling retain on this Canary object and then never releasing it.

痴意少年 2024-10-26 06:43:24

自动释放的对象在其池耗尽之前不会被释放。因此,如果您使用自动释放缓冲区循环遍历图像,那么每次循环时最好创建并排出一个池。

Autoreleased objects do not get released until their pool is drained. So, if you are looping through images with an autoreleased buffer, it would be good to create and drain a pool every time through the loop.

秋心╮凉 2024-10-26 06:43:24

Mike Ash 发表了一篇名为 Autorelease 的更多乐趣 的博文,其中介绍了解释了这个问题的根源。引用:

众所周知,每次你去
通过事件循环,Cocoa 吹响
拆除旧泳池并建造一个新泳池
为你,让你的一切
自动释放的对象消失了,你的
新的进入新的池子。那
这样你就永远不会建造更多的物体
比在单个过程中产生的
事件循环循环。关键词是“事件循环”。在
苹果无限智慧,物尽其用
不是真正的 NSEvents 不是
触发池。

我目前正在开发一个应用程序
花费大量时间在后台
做一些黑暗的、难以形容的事情
主线程上的 NSStreams。我
遇到了一个错误,我的其中一个
物体可能会被破坏
处理流事件的中间,
这使得它可以接受其他的
之后的流事件
解除分配。 (...)

显而易见的解决办法就是简单地做
[[self keep] autorelease] 之前
拨打问题电话。并修复它
做了,除了我的 dealloc
发生在我的活动中间
处理程序,它根本没有发生过。

直到我点击应用程序的 Dock 图标。

至少解决方案很简单。邮政
中的 NSApplicationDefined 事件
流事件处理程序和自动释放
对象按计划被销毁。

我发誓我必须从头到尾阅读该博客,这是一次很好的时间投资。

There’s a blog post by Mike Ash called More Fun With Autorelease that explains the source of this problem. Quote:

As everybody knows, every time you go
through the event loop, Cocoa blows
away the old pool and makes a new one
for you, so that all of your
autoreleased objects go away and your
new ones go into a fresh pool. That
way you never build up more objects
than get produced during a single
event loop cycle. The key word is “event loop”. In
Apple's infinite wisdom, things that
aren't real actual NSEvents don't
trigger the pool.

I'm currently working on an app that
spends a lot of time in the background
doing dark, unspeakable things with
NSStreams on the main thread. I
encountered a bug where one of my
objects can get destroyed in the
middle of handling a stream event,
which left it open to getting other
stream events after it was
deallocated. (…)

The obvious fix was to simply do
[[self retain] autorelease] before
making the problem call. And fix it it
did, except instead of my dealloc
happening in the middle of my event
handler, it never happened at all.

Until I clicked on my app’s dock icon.

At least the solution was easy. Post
an NSApplicationDefined event in the
stream event handler, and autoreleased
objects get destroyed on schedule.

I swear I have to read the blog from cover to cover, it’s a good time investment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文