【问题标题】:Mutable Copy of NSData in NSMutableDIctionary causing memory leakNSMutableDIctionary 中 NSData 的可变副本导致内存泄漏
【发布时间】:2011-07-17 11:21:32
【问题描述】:

在我的代码中,我在 viewDidAppear 中定义了一个 NSDictionary,如下所示:

dataDictionary = [[NSMutableDictionary alloc] init];

然后稍后在 loadData 方法中,我像这样加载 NSDictionary 的可变副本:

      [dataDictionary setObject:[receivedData mutableCopy] forKey:[theConnection description]];

稍后,当我切换到不同的视图时,我会卸载我的 dataDictionary 以节省内存。在 viewDidDissappear 中,我输入:

[数据字典发布]; 数据字典=nil;

我还在 dealloc 中发布了 dataDictionary。

但是,好像有一个与 mutableCopy 相关的内存泄漏,而这是我制作的唯一 mutableCopy,所以它必须来自上图所示的 mutableCopy。有谁知道为什么这可能会泄漏?我认为 mutableCopy 除了为 NSMutableDictionary 所做的分配外,还会进行另一个分配,但我不确定如何处理,因为 mutableCopy 在字典内并且字典已被释放。

提前谢谢...

【问题讨论】:

  • 它看起来不错,如果您不再使用receivedData,则需要[receivedData release],否则至少在dealloc中释放receivedData
  • 是的,在我将收到的数据作为副本添加到字典后,我确实释放了它......

标签: objective-c cocoa-touch nsdata memory-leaks nsmutabledictionary


【解决方案1】:

试试这样的

[dataDictionary setObject:[[receivedData mutableCopy] autorelease] forKey:[theConnection description]];

【讨论】:

  • 当我稍后尝试从 dataDictionary 中删除其中一个对象时,这似乎会导致崩溃和“malloc: *** error for object 0x5e3cbd0: double free”错误。
【解决方案2】:

mutableCopy 方法没有返回自动释放的对象,因此您收到的 NSMutableData 保留计数为 1,然后将其添加到字典中,该字典也保留它 - 这意味着当您删除它时它不会被销毁从字典中或当字典被释放时,您将丢失对它的任何引用,并且该对象将被泄露。

就像其他人建议的那样,在将可变副本添加到 dataDictionary 时自动释放它。

[dataDictionary setObject:[[receivedData mutableCopy] autorelease] forKey:[theConnection description]];

或者做类似的事情

NSMutableData *mutableData = [receivedData mutableCopy];
[dataDictionary setObject:mutableData forKey:[theConnection description]];
[mutableData release];

【讨论】:

  • 我尝试了第二个选项,但我仍然得到泄漏。仔细查看后,泄漏的不是 NSMutableData,而是 NSConcreteMutableData。它说具体的事实对您来说是否意味着任何可能帮助我理解这次泄漏的事情?
【解决方案3】:

就像 Benj 和 Zaky 已经提到的那样,您应该在 mutableCopy 上调用 autorelease,但您还必须确保不要在 dealloc 和 viewDidDisappear: 中释放 dataDictionary。由于创建时 dataDictionary 的保留计数为 1,并且 viewDidDisappear: dealloc 都可能在您的视图被销毁时被调用,因此您最终会尝试释放已被释放的对象。

确保您只在 dealloc 中释放 dataDictionary 并且您不会看到您提到的“双重释放”错误消息。在 viewDidDisappear: 中对 ivar 调用“释放”无论如何都是一个冒险的提议,因为 viewDidDisappear: 在视图的整个生命周期中被多次调用(例如,如果其他视图控制器被推送到您的导航堆栈上)。如果你想确保节省内存,最好在 viewDidLoad 中创建东西并在 viewDidUnload 中释放东西。 viewDidUnload 在内存不足的情况下被调用,所以这正是你在这种情况下想要的。

您可能想查看这篇文章以获取有关 Cocoa 引用计数约定的详细说明:Object ownership in stringWithString and initWithString in NSString

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多