【问题标题】:Cross retain trouble交叉保留麻烦
【发布时间】:2011-08-20 05:51:24
【问题描述】:

当两个对象相互保留时,如何解决交叉保留情况?

考虑这个类结构:

容器.h

@interface Container : NSObject {
    NSObject *child;
}

@property (nonatomic, retain) NSObject *child;
@end

容器.m

@implementation Container

@synthesize child;

- (void)dealloc {
    [child release];
    [super dealloc];
}

@end

那么在测试内存保留计数时:

- (void)testDoubleRetain {
    Container *A = [[Container alloc] init];
    Container *B = [[Container alloc] init];

    NSLog(@"A retainCount: %d", [A retainCount]);//returns 1
    NSLog(@"B retainCount: %d", [B retainCount]);//returns 1
    [A setChild:B];
    [B setChild:A];

    NSLog(@"A retainCount: %d", [A retainCount]);//returns 2
    NSLog(@"B retainCount: %d", [B retainCount]);//returns 2

    [A release];
    [B release];

    NSLog(@"A retainCount: %d", [A retainCount]);//returns 1
    NSLog(@"B retainCount: %d", [B retainCount]);//returns 1
}

因此,据我了解,保留计数应该显示正确的计数。但是我如何最终真正释放对象,因为在这段代码之后,这两个对象将留在内存中。

【问题讨论】:

  • setChild 函数有什么作用?此外,A 和 B 是彼此的孩子似乎很奇怪。这什么时候有用?
  • setChild 保留你给它的对象。我遇到过这种情况,不同类型的对象相互保留,但为了简单起见,我在这里的示例使用了相同的问题。但在现实生活中,这将是两种不同的类类型

标签: objective-c memory-management memory-leaks retaincount


【解决方案1】:

简单的解决方法可能是在释放对象之前将子对象设为 nil:

A.child = nil;
[A release];

但为了避免您的问题,可能值得重新考虑您的一般程序结构,这样您就不需要让 2 个对象相互保留(可能是它们的关系允许使用“分配”属性而不是“保留”,而您可以确保它们不会被其他方式过早地释放 - 例如,将它们全部放入某个全局容器中 - 这一切都取决于您的实际上下文)

【讨论】:

  • 这似乎是解决方案,如果 m 在一个对象上使用 assign 并且该对象在我之前被释放,我最终会调用一个已释放的对象并崩溃。对这种情况有什么想法吗?
  • 如果您使用 assign 属性,那么您需要确保您的对象不会以其他方式被释放 - 可能有 1 个外部对象专用于保留您的容器 - 您需要做什么可能取决于您的应用的上下文和一般架构
  • 谢谢弗拉德,这似乎是 m 将要采取的选择。我将测试 assign 选项,并确保我的对象在我们完成之前没有被释放,然后我将安全地使用 assign 属性。
  • 我检查了分配属性而不是保留,这似乎是更好的解决方案。谢谢你的帮助男人
【解决方案2】:

首先,do not use retainCount。它不会像你想的那样。

这里的正常做法是让孩子或容器保留另一个,这将打破循环。如果这不可能,请提供一个必须显式调用的函数,以告诉容器您已完成它,此时它将释放子容器。

【讨论】:

  • 是的,我一直在阅读有关 retainCount 不准确的信息。据我所知,大多数情况下,除非您使用 UIKit 并添加子视图并且在该对象的生命周期结束时不删除它们,否则您最终会得到一个保留的对象。
  • @Edward,在处理retaintCount 时有很多问题。在您的情况下,您在释放对象的所有权后调用 retainCount,这始终是一个错误并且永远不会返回零,因此它返回 1 的事实实际上没有任何意义。更正确的做法是将日志记录添加到您的 dealloc 方法中。这样,您将具体知道对象实例是否已被释放。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 2010-11-11
  • 2011-06-12
  • 1970-01-01
相关资源
最近更新 更多