对象被释放但没有调用 dealloc

Posted

技术标签:

【中文标题】对象被释放但没有调用 dealloc【英文标题】:Object being freed but dealloc not called 【发布时间】:2014-08-20 15:06:19 【问题描述】:

在我的应用程序的某个时刻,我从其父视图控制器(我们称其为 B)中删除了一个视图控制器(我们称其为 A)。而且即使 A 不再被引用,它的 dealloc 方法也不会被调用。

我用仪器查了一下,A真的被释放了。活体(A类)数量为0。

NSZombie 未启用,我看到它可能会干扰 dealloc 调用。

dealloc 方法被调用的唯一时刻是视图控制器 B 被释放的时候。那一刻,堆栈跟踪是这样的:

#0  0x0001ac78 in -[MyViewController dealloc] <-- This is A
#1  0x021061bf in _objc_deallocOnMainThreadHelper ()
#2  0x029f34d0 in _dispatch_client_callout ()
#3  0x029e1726 in _dispatch_main_queue_callback_4CF ()
#4  0x0274443e in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#5  0x026855cb in __CFRunLoopRun ()
#6  0x026849d3 in CFRunLoopRunSpecific ()
#7  0x026847eb in CFRunLoopRunInMode ()
#8  0x046095ee in GSEventRunModal ()
#9  0x0460942b in GSEventRun ()
#10 0x00db4f9b in UIApplicationMain ()
#11 0x00028ea2 in main at /../main.m:17

我不确定dealloc是如何触发的

知道这里会发生什么吗?

-- 编辑

我使用类方法创建视图控制器 A:

+ (instancetype)viewController

    return [[MyViewController alloc] init];

奇怪的是,当我用 [[MyViewController alloc] init] 替换对此类方法的调用时,一切都按预期工作。我不知道发生了什么。有什么想法吗?

【问题讨论】:

这里没有足够的信息,您将类称为“A”和“B”,但哪个是 MyViewController?堆栈跟踪不完整(从 1 跳到 10) - 您需要缩放窗口以打开所有条目。对于最初的问题 - A 是如何分配和使用的?显示更多代码。 您是否有一些想要在 dealloc 中发生的逻辑,或者您对垃圾回收的工作原理感到好奇? @BrianWalker :这是我在 Xcode 中的完整堆栈跟踪,1 到 10 之间没有任何内容。或者我不知道如何找到它。我会尝试添加更多代码 @brodney :ARC 不是垃圾收集器。是的,我需要在 dealloc 中执行一些重要操作 我的意思是问你是否依赖它们在某个时间发生。您可以在堆栈跟踪面板底部看到 1-10 之间的滑块。 【参考方案1】:

我终于找到了发生的事情。

未被释放的视图控制器是通过类方法创建的,例如:+ (instancetype) createMyViewController

这种方法返回自动释放对象。

我唯一的猜测是,在我的情况下,自动释放池已经耗尽得太晚了。在适当的代码周围添加一个@autoreleasepool 块可以解决所有问题。

【讨论】:

然而你却声称“活体的数量是0”。如果一个对象正在等待自动释放,它仍然是“活着的”。 如果我的理解是正确的,当一个对象收到一个自动释放消息时,它会一直存活到它的自动释放池被耗尽。据此,在我的情况下,活着的对象的数量不应该是 0,但也许 Instruments 认为该对象不再是活着的(因为没有人对该对象有引用,所以该对象将在稍后自动释放时被安全地释放池已排干)。你怎么看? 如果该工具只是报告引用计数,这在当前版本的 ios 中是可疑的。【参考方案2】:

查看这些视图控制器生命周期方法。其中之一可能是您在 dealloc 中拥有的代码的正确位置,您可以指望它们在规定的时间被调用。 Dealloc 应该只用于内存清理,例如免费。

- (void)viewWillDisappear:(BOOL)animated

- (void)viewDidDisappear:(BOOL)animated

【讨论】:

我只在我的 dealloc 中进行内存清理。我只需要立即完成。这就是为什么我试图理解为什么当我的控制器没有被任何其他对象引用时不调用 dealloc。查看我的答案,我找到了解决方法。 现在明白了,很有意义,很高兴你明白了。

以上是关于对象被释放但没有调用 dealloc的主要内容,如果未能解决你的问题,请参考以下文章

当我们显式调用 finalize() 时,对象内存是不是被释放? [复制]

对象在 UIAlertView 委托被调用之前被释放

我应该在重新分配之前调用分配给保留属性的自动释放对象的释放吗?

析构函数为啥能释放对象内存?

如何允许在回调时释放对象?

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