NSMutableDIctionary 中 NSData 的可变副本导致内存泄漏
在我的代码中,我在 viewDidAppear 中定义了一个 NSDictionary,如下所示:
dataDictionary = [[NSMutableDictionary alloc] init];
然后在 loadData 方法中,我加载 NSDictionary 的可变副本,如下所示:
[dataDictionary setObject:[receivedData mutableCopy] forKey:[theConnection description]];
后来,当我切换到不同的视图时,我卸载 dataDictionary 以节省内存。在 viewDidDissappear 中,我输入:
[数据字典发布]; dataDictionary=nil;
我还在 dealloc 中释放了 dataDictionary。
但是,似乎存在与 mutableCopy 相关的内存泄漏,并且这是我制作的唯一 mutableCopy,因此它必须来自上面显示的 mutableCopy。有人知道为什么这可能会泄漏吗?我认为 mutableCopy 除了为 NSMutableDictionary 进行的分配之外还进行了另一个分配,但我不确定如何处理它,因为 mutableCopy 位于字典内部并且字典已释放。
提前致谢...
In my code, I define a NSDictionary in viewDidAppear like this:
dataDictionary = [[NSMutableDictionary alloc] init];
then later in a loadData method, I load a mutable copy of the NSDictionary like this:
[dataDictionary setObject:[receivedData mutableCopy] forKey:[theConnection description]];
Later, when I switch to a different view, I unload my dataDictionary to save memory. In viewDidDissappear, I put:
[dataDictionary release];
dataDictionary=nil;
and I also release dataDictionary in dealloc.
However, it seems that there is a memory leak related to mutableCopy, and this is the only mutableCopy that I make, so it must be from the mutableCopy shown above. Does anybody have any idea why this might be leaking? I am thinking that mutableCopy makes another allocation besides the allocation made for the NSMutableDictionary, but I'm not sure how to deal with that since the mutableCopy is inside the dictionary and the dictionary is released.
Thanks in advance...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
mutableCopy 方法不会返回自动释放的对象,因此您收到保留计数为 1 的 NSMutableData,然后将其添加到字典中,该字典也保留它 - 这意味着当您从字典中删除它时它不会被销毁或者当字典被释放时,您将丢失对它的任何引用,并且对象将被泄漏。
因此,就像其他人建议的那样,在将可变副本添加到 dataDictionary 时自动释放它。
或者做类似的事情
the mutableCopy method is not returning an autoreleased object, so you're receiving your NSMutableData with a retain count of 1, then you add it to the dictionary which also retains it - which means it will not be destroyed when you remove it from the dictionary or when the dictionary is dealloced, you will lose any reference to it, and the object will be leaked.
so like someone else suggested, autorelease the mutable copy when adding it to the dataDictionary.
or do something like
尝试这样的事情
Try something like this
就像 Benj 和 Zaky 已经提到的那样,您应该在 mutableCopy 上调用 autorelease,但您还必须确保不要在 dealloc 和 viewDidDisappear: 中释放 dataDictionary。由于 dataDictionary 在创建时的保留计数为 1,并且 viewDidDisappear: 和 dealloc 都可能在视图被销毁时被调用,因此您最终将尝试释放已释放的对象。
确保您只在 dealloc 中释放 dataDictionary,并且您不会看到您提到的“双重释放”错误消息。无论如何,在 viewDidDisappear: 中的 ivar 上调用“release”是一个危险的提议,因为 viewDidDisappear: 在视图的整个生命周期中被多次调用(例如,如果其他视图控制器被推送到导航堆栈上)。如果你想确保节省内存,最好在 viewDidLoad 中创建内容并在 viewDidUnload 中释放内容。 viewDidUnload 在内存不足的情况下被调用,因此这正是您在这种情况下想要的。
您可能想查看这篇文章,了解有关 Cocoa 引用计数约定的详细说明:NSString 中的 stringWithString 和 initWithString 中的对象所有权
Like Benj and Zaky already mentioned, you should call autorelease on your mutableCopy, but you also have to make sure not to release dataDictionary in both dealloc and viewDidDisappear:. Since dataDictionary has a retain count of 1 when you create it, and both viewDidDisappear: and dealloc probably get invoked when your view is destroyed, you'll wind up trying to release an object that's already been freed.
Make sure you only release dataDictionary in dealloc and you won't see the "double free" error message you mentioned. Invoking "release" on an ivar in viewDidDisappear: is a risky proposition anyway, since viewDidDisappear: gets invoked multiple times throughout the lifecycle of a view (e.g., if other view controllers get pushed onto your navigation stack). If you want to make sure to save memory, it's best to create stuff in viewDidLoad and to release stuff in viewDidUnload. viewDidUnload gets called in low-memory situations, so it's exactly what you want in this situation.
You may want to check out this post for a detailed description about Cocoa reference counting conventions: Object ownership in stringWithString and initWithString in NSString