无法弄清楚如何修复iPhone上的内存泄漏

时间:2010-12-05 21:15:37

标签: iphone objective-c memory-leaks instruments

我正在运行Leaks工具并在我的Dictionary mutableDeepCopy中发现了大量泄漏,但我无法弄清楚代码有什么问题。有什么建议吗?

@interface RootViewController : UIViewController{

  NSDictionary *immutableDictionary;
  NSMutableDictionary *mutableDictionary;
}

以下是在Instruments

中突出显示的代码行
self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

以下是创建Dictionary的可变副本的方法

@interface NSDictionary(MutableDeepCopy)
  -(NSMutableDictionary *)mutableDeepCopy;
@end

这是方法实现,我突出了Leaks所说的100%泄漏的代码

- (NSMutableDictionary *) mutableDeepCopy {
    NSMutableDictionary *dictionaryToReturn = [NSMutableDictionary dictionaryWithCapacity:[self count]];
    NSArray *keys = [self allKeys];

    for(id key in keys) {
        id value = [self valueForKey:key];
        id copy = nil;
        if ([value respondsToSelector:@selector(mutableDeepCopy)]) {
            copy = [value mutableDeepCopy];
        } else if ([value respondsToSelector:@selector(mutableCopy)]) {
            copy = [value mutableCopy]; //This is the Leak
        }
        if (copy == nil) {
            copy = [value copy];
        }
        [dictionaryToReturn setValue:copy forKey:key];
    }
    return dictionaryToReturn;
}

3 个答案:

答案 0 :(得分:3)

您的财产如何申报?如果是retaincopy,那么这不会泄漏。

你的问题是名称mutableDeepCopy表明它返回一个保留对象,而不是实际发生的自动释放对象。

修改 在mutableDeepCopy本身,你需要在添加到字典后释放copy变量。

答案 1 :(得分:3)

您需要根据Apple的Memory Management Rules进行分析。

从这一行开始:

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

我希望mutableDeepCopy返回我拥有的对象,所以在某些时候我需要释放或自动释放它。 e.g。

NSMutableDeepCopy* temp = [self.immutableDictionary mutableDeepCopy];
self.mutableDictionary = temp;
[temp release];

self.mutableDictionary = [[self.immutableDictionary mutableDeepCopy] autorelease];

所以现在我们需要看一下mutableDeepCopy。因为它在名称中有'copy',它需要返回一个“拥有”的对象,实际上这意味着“忘记”释放返回的对象。在第一行中创建返回的对象时,您已经失败了,因为dictionaryWithCapacity:为您提供了一个您不拥有的对象。替换为

NSMutableDictionary *dictionaryToReturn = [[NSMutableDictionary alloc] initWithCapacity:[self count]];

现在你拥有它。

让mutableDeepCopy遵守规则非常重要,因为这意味着您可以处理从mutableDeepCopy,mutableCopy返回的对象并以完全相同的方式进行复制。在所有三种情况下,您拥有插入到数组中的对象副本。因为你拥有它,你必须释放它,否则你会发现它会泄漏。所以,在循环结束时,你需要

[copy release];

那会阻止泄漏。

答案 2 :(得分:2)

mutableCopy增加对象的保留计数,setValue:forKey:也是如此。这意味着当dictionaryToReturn被解除分类时,调用mutableCopy的对象的保留计数为一。

尝试这样做:

copy = [[value mutableCopy] autorelease];