-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗?
Posted
技术标签:
【中文标题】-dealloc 方法在拥有数组 dealloc\'d 时不被调用...应该吗?【英文标题】:-dealloc method not called when owning array dealloc'd... should it?-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗? 【发布时间】:2011-01-25 01:40:39 【问题描述】:这是 Foundation 应用程序中的两段 Objective-C 代码。这段代码在一个函数中:
[arrayOfObjects addObject:[[TheShape alloc] init]];
NSLog(@"%@", arrayOfObjects); // log verifies "<TheShape..." is in the array
[arrayOfObjects release];
在我的 TheShape 类中,我有这个 dealloc
覆盖方法:
- (void)dealloc
NSLog(@"TheShape dealloc called.");
[super dealloc];
虽然我的程序可以正常工作,但它并没有按我预期的方式工作。当发送[arrayOfObjects release]
消息时,我希望看到“TheShape dealloc...”字符串出现在日志中。没有。
Q1:为什么不呢?
所以我挖掘了一下并简化了一些事情。如果我这样做更简单:
TheShape *aShape = [[TheShape alloc] init];
[aShape release];
调试消息仍然没有出现在日志中。
Q2:为什么不呢?
但如果我这样做:
TheShape *aShape = [TheShape new];
[aShape release];
调试消息确实出现在日志中。如果我将第一个示例中的 alloc/init 也更改为 new
,调试消息也会出现在日志中。
Q3:为什么?
显然,我在 alloc/init/release 周期(Q 的 1 和 2)以及假定的 new
和 alloc/init
(Q3)的等效性中遗漏了一些概念性的东西。任何人都可以向我指出一个教程,该教程可以像我一样对难以思考的事物进行更多解释吗?
谢谢,
比尔
【问题讨论】:
TheShape *aShape = [[TheShape alloc] init];
和TheShape *aShape = [TheShape new];
应该没有区别。
【参考方案1】:
你有没有在你的课堂上覆盖+new
?它应该与+alloc/-init
做完全相同的事情。
无论如何,你的第一行
[arrayOfObjects addObject:[[TheShape alloc] init]];
正在泄漏您的 TheShape
实例。你应该把它转成
[arrayOfObjects addObject:[[[TheShape alloc] init] autorelease]];
【讨论】:
我没有覆盖 +new 类,但如果我有的话,我可以看出哪里会出现问题。我希望 new 的行为与 alloc/init 完全一样,但这并不是出于某种奇怪的原因。我仍然对此感到疑惑。 不过,制作 TheShape 自动释放就可以了。第一次发生了什么?是的,我分配/初始化,所以拥有该对象,但 arrayOfObjects 最终不必为我跟踪它吗?这是我清楚地认为应该发生一件事而 Objective-C 内存管理的基本规则似乎不一致的情况之一。澄清将不胜感激。 数组不会“接管”您对对象的所有权。它正在增加自己的所有权。一个对象可以由多个其他对象拥有。在这种情况下,数组拥有它,但您的本地方法也是如此。您需要在阵列拾取它后放弃对它的所有权。 啊,zneak(下)为我回答了这个问题。 (我猜,提前阅读是值得的。)【参考方案2】:没有理由调用 dealloc
方法:您的对象仍然具有非零引用计数。
每当您创建一个对象时,它的引用计数为 1。一旦该计数达到 0,它就会被释放。内存管理有一些特定的规则可以帮助我们保持清醒。这些规则谈到“对象所有权”。
基本上,如果您满足以下条件之一,您将成为对象的所有者:
你在对象上调用retain
;
您通过在另一个对象上调用copy
或mutableCopy
来获取一个对象;
您在对象上调用alloc
方法。
当您拥有一个对象时,您有责任在不再需要它时释放它。只有在没有人需要时才会删除它。
在你的 sn-p 中,你创建你传递给你的数组的对象。您的数组开始使用它,因此它会在其上调用retain
(因此它在被持有时保持活动状态)。但是,一旦您 release
数组,您的对象仍然需要由 您 释放,因为您调用了 alloc
方法。
编辑简单的 sn-p:
TheShape *aShape = [[TheShape alloc] init];
[aShape release];
应该显示消息,但是。 :/
我认为这没有发生的原因有两个:
您使用alloc
、init
或release
方法做了一些奇怪的事情(在这种情况下,请发布您的代码);
你在垃圾收集环境中运行,dealloc
将永远不会被调用(在这种情况下你应该使用finalize
)。虽然我不明白为什么 +new
然后 release
会给出预期的结果。
【讨论】:
-init
并不意味着所有权。另一方面,名称中包含alloc
或new
的方法可以。
虽然我理解 Bavarious 所说的(CAN=ownership),但我不确定他在您的原始帖子中指的是什么……哦,没关系。我刚刚点击了修订链接。知道了。谢谢,伙计们!以上是关于-dealloc 方法在拥有数组 dealloc'd 时不被调用...应该吗?的主要内容,如果未能解决你的问题,请参考以下文章
我如何在Javascript中拥有可变长度数组的前3个元素[重复]