为啥 Instruments 将此报告为内存泄漏?
Posted
技术标签:
【中文标题】为啥 Instruments 将此报告为内存泄漏?【英文标题】:Why is Instruments reporting this as a memory leak?为什么 Instruments 将此报告为内存泄漏? 【发布时间】:2009-04-07 18:09:31 【问题描述】:我有一些代码如下所示:
NSMutableArray *bar = [[NSMutableArray alloc] initWithCapacity:0];
NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
[foo setObject:[NSNull null] forKey:@"yay"];
[bar addObject:foo];
[foo release];
仪器显示 foo 正在泄漏。我明白为什么会这样。 foo 在 alloc'd 时的保留计数为 1。然后当 bar addObject 的 foo 时,保留计数变为 2。后来当我释放 foo 时,它又回到 1。仍然是泄漏。但是,稍后在我的代码中,(在一个单独的方法中,这就是为什么我认为这可能会显示为泄漏)
[bar removeAllObjects];
如果我稍后执行 removeAllObjects,为什么 foo 显示为泄漏?
** 注意 **
我没有将它包含在我的原始帖子中,但 bar 确实在类 dealloc 方法中发布。
【问题讨论】:
在哪里调用 [bar removeAllObjects]?它是无限期地调用吗? (例如在 dealloc 方法中)。在 [foo release] 之后立即调用 removeAllObjects 会导致仍然观察到泄漏吗? Perspx:bar是在dealloc方法中释放的,它是一个类实例。否则,我在上课期间需要它。我确实在 dealloc 中释放了它。 【参考方案1】:我认为(而且我认为您也暗示了这种可能性)Instruments 将其标记为潜在泄漏,因为它没有向前看足够远,无法看到该酒吧将负责用于在所述单独方法中删除/释放其所有对象..
【讨论】:
我想就是这样。 Instruments 可能会标记 bar 是在此方法的范围内分配的,但并未在此释放。 是的,我以前也遇到过类似的问题。 Instruments 在某些情况下肯定会有所帮助,但它永远无法取代坐下来手动查看代码。 阿门。我不认为有任何东西可以代替长时间手动查看代码:) 呃,所以如果它没有以相同的方法释放/释放,这是否意味着我的代码可能是错误的,应该重新设计? 不,Instruments 不能那样工作;它根本不看你的代码。如果 Instruments 报告泄漏,则意味着您的程序中没有任何内容指向该对象。最可能的解释是 bar(或其所有者)的保留不平衡。【参考方案2】:鉴于您显示的内容,bar
永远不会被释放。调用[bar removeAllObjects]
只会删除它包含的对象。相反,您应该在完成bar
后致电[bar release]
。这将自动释放 bar
持有的所有对象,并释放 bar 对象本身。
您声明您了解内存管理概念,因此您可能只是没有在示例中显示bar
正在被释放。
编辑: 我认为 craig 在his answer 中的想法是正确的。避免警告的一种方法(也许)是在init
类方法中分配bar
。当涉及到成员变量时,我通常发现在 init
和 dealloc
方法之间保持对称是有益的,这将是一个很好的例子:
- (id)init
if ((self = [super init]) == nil) return nil;
bar = [[NSMutableArray alloc] initWithCapacity:0];
return self;
- (void)dealloc
[bar release];
[super dealloc];
- (void)YourMethod
NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
[foo setObject:[NSNull null] forKey:@"yay"];
[bar addObject:foo];
[foo release];
【讨论】:
我想这可能是它。如果对 bar 的引用在没有先释放的情况下丢失,则 foo 将被标记为泄漏。 他的评论表明 bar 实际上已发布。哦,好吧!【参考方案3】:NSMutableArray 应该在调用 removeAllObjects 时释放它。您不需要将其释放或添加到自动释放池中。
来自 O'Reilly 的内存管理章节:
当您将对象添加到集合时,它会被保留。当您从集合中删除一个对象时,它就会被释放。释放一个集合对象(比如一个 NSArray)也会释放存储在其中的所有对象。
也许乐器中发生了其他事情?
【讨论】:
以上是关于为啥 Instruments 将此报告为内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章