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

发布于 2024-10-06 11:28:05 字数 1274 浏览 2 评论 0原文

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

@interface RootViewController : UIViewController{

  NSDictionary *immutableDictionary;
  NSMutableDictionary *mutableDictionary;
}

这是 Instruments 中突出显示的代码行

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

这是创建字典的可变副本的方法

@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;
}

I was running Leaks tool and discovered a massive leak in my Dictionary mutableDeepCopy but I can't figure out what's wrong with the code. Any suggestions?

@interface RootViewController : UIViewController{

  NSDictionary *immutableDictionary;
  NSMutableDictionary *mutableDictionary;
}

Here is the line of code that's highlighted in Instruments

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

Here is the method for creating a mutable copy of a Dictionary

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

Here is method implementation, I've highlighted the code that Leaks saids is leaking 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

隱形的亼 2024-10-13 11:28:05

您需要根据Apple的内存来分析这一点管理规则

从这一行开始:

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

我希望 mutableDeepCopy 返回我拥有的对象,因此在某些时候我需要释放或自动释放它。例如

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 返回的对象。在所有三种情况下,您都拥有插入到数组中的对象副本。因为你拥有它,所以你必须释放它,否则它就会像你发现的那样泄漏。因此,在循环结束时,您需要

[copy release];

阻止泄漏。

You need to analyse this in light of Apple's Memory Management Rules.

Starting with this line:

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];

I would expect mutableDeepCopy to return an object I own, so at some point I need to release or autorelease it. e.g.

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

or

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

So now we need to look at mutableDeepCopy. Because it has 'copy' in the name it needs to returned an "owned" object which, in practice means "forgetting" to release the returned object. You have already failed to do that when you create the returned object in the first line, since dictionaryWithCapacity: gives you an object you do not own. Replace it with

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

Now you own it.

It is important that you make your mutableDeepCopy obey the rules because it means you can treat the objects returned from mutableDeepCopy, mutableCopy and copy in exactly the same way. In all three cases you own the object copy that you insert into the array. Because you own it, you must release it or it'll leak as you found out. So, at the end of the loop, you need

[copy release];

That'll stop the leak.

2024-10-13 11:28:05

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

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

编辑:
而在 mutableDeepCopy 本身,您需要在添加到字典后释放 copy 变量。

How is your property declared? If is is retain or copy, then this doesn't leak.

Your problem is that the name mutableDeepCopy suggests that it returns a retained object, and not an autoreleased one as it actually does.

Edit:
And at the mutableDeepCopy itself, you need to release the copy variable after adding to the dictionary.

花开浅夏 2024-10-13 11:28:05

mutableCopy 会增加对象的保留计数,setValue:forKey: 也是如此。这意味着当 dictionaryToReturn 被释放时,调用了 mutableCopy 的对象的保留计数仍然为 1。

尝试这样做:

copy = [[value mutableCopy] autorelease];

mutableCopy increments the retain count of the object, as does setValue:forKey:. This means that when dictionaryToReturn is dealloc'ed, the object that had mutableCopy called still has a retain count of one.

Try doing this instead:

copy = [[value mutableCopy] autorelease];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文