根据仪器的 iOS 内存泄漏

发布于 2024-12-06 01:30:05 字数 4055 浏览 0 评论 0原文

仪器中内存泄漏的屏幕截图

请帮忙!我已经阅读了内存管理规则,但也许我在某个地方错过了它们。 Instruments 告诉我以下代码存在泄漏:

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil];
NSArray *objects 
    = [NSArray arrayWithObjects:sPlateToAdd, [
         [[NSNumber alloc] initWithInt:1] autorelease], 
         [[[NSNumber alloc] initWithInt:1] autorelease], 
         nil];

NSMutableDictionary *dPlateToAdd 
    = [NSMutableDictionary dictionaryWithObjects:objects forKeys:keys];  // 93.4%        
[self.aFinals addObject:dPlateToAdd];    // 6.6%

Keys 和 Objects 数组没有被分配或初始化,所以我认为我不需要释放它们?

然后对象内部的数字会被自动释放,所以它们没问题,不是吗? sPlateToAdd 是一个字符串,它被传递到该代码所在的方法中,所以我不是它的所有者,所以我不需要释放它。或者我是?

我一定是在某个地方做错了什么。

该应用程序在 iPad 上运行完全正常,但在 iPhone 3GS 上运行速度很慢,我希望修复此内存泄漏可能会加快速度一点...

这是创建 self.aFinals 的方法,它传递一个字符串来自文本输入。我省略了一些行,但 self.aFinals 不与它们交互

-(id)initWithTerm:(NSString *)thisTerm {
    ...
    ...
    self.aFinals = [[NSMutableArray alloc] init];

    return self;
}

然后我有大约 5 个嵌套循环,在所有循环中间调用 addPlateToFinals 3 次,创建 thisPlate,其中变成 sPlateToAdd

// replace 1st occurance
NSString *thisPlate = [thisBase
    stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:
        @"(^[^%@]+)%@(.*$)", 
        thisChar, 
        thisChar] 
     withString:[NSString stringWithFormat:@"$1%@$2", thisSub]
     ];

     [self addPlateToFinals:thisPlate withSubCount:thisSubCount];
 // replace 2nd occurance
 thisPlate = [thisBase
     stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:
         @"(^[^%@]+%@.*)%@",    
         thisChar, 
         thisChar, 
         thisChar] 
     withString:[NSString stringWithFormat:@"$1", thisSub]
     ];

 // then it does it again, with slightly different regex

这是泄漏来自的完整方法:

-(void)addPlateToFinals:(NSString *)sPlateToAdd withSubCount:(NSNumber *)nSubCount {
// plate must be less than 7 characters and great than 2 chars
if (
    [sPlateToAdd length] <= [self.nPlateMax intValue] &&
    [sPlateToAdd length] >= [self.nPlateMin intValue]
    ) {    

    NSMutableArray *aSearchFinals = [self arrayOfFinals];

    // add plate if it is not already in the finals array   
    if(![aSearchFinals containsObject:sPlateToAdd]) {

        // filter out results that cannot be converted to valid plates
        NSPredicate *potential = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{0,3}[0-9]{1,3}[a-z]{0,3}$'"];
        NSPredicate *impossible1 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2,3}[a-z]{2}$'"];
        NSPredicate *impossible2 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z][0-9]{3}$'"];
        NSPredicate *impossible3 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2}$'"];
        NSPredicate *impossible4 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[0-9]{2}[a-z]{2}$'"];

        if(
            [potential evaluateWithObject: sPlateToAdd] && 
            ![impossible1 evaluateWithObject: sPlateToAdd] &&
            ![impossible2 evaluateWithObject: sPlateToAdd] &&
            ![impossible3 evaluateWithObject: sPlateToAdd] &&
            ![impossible4 evaluateWithObject: sPlateToAdd]
        ){                  

            NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil];
            NSArray *objects = [NSArray arrayWithObjects:
                                    sPlateToAdd, 
                                    [[[NSNumber alloc] initWithInt:1] autorelease], 
                                    [[[NSNumber alloc] initWithInt:1] autorelease], 
                                    nil
                                ];

            NSDictionary *dPlateToAdd = [NSDictionary dictionaryWithObjects:objects forKeys:keys];          
            [self.aFinals addObject:dPlateToAdd];   
        }
    }
}

}

Screen shot of memory leak in instruments

Please help! I've read the memory management rules, but maybe I'm missing them point somewhere. Instruments is telling me I've got leaks on the following code:

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil];
NSArray *objects 
    = [NSArray arrayWithObjects:sPlateToAdd, [
         [[NSNumber alloc] initWithInt:1] autorelease], 
         [[[NSNumber alloc] initWithInt:1] autorelease], 
         nil];

NSMutableDictionary *dPlateToAdd 
    = [NSMutableDictionary dictionaryWithObjects:objects forKeys:keys];  // 93.4%        
[self.aFinals addObject:dPlateToAdd];    // 6.6%

the Keys and Objects arrays aren't being alloc'ed or init'ed, so I dont think I need to release those?

Then the numbers inside Objects are being auto released, so they're ok aren't they?
And sPlateToAdd is a string that gets passed into the method this code is in, so I'm not the owner of that, so I don't need to release it. Or am I?

I've got to be doing something wrong somewhere.

The app runs completely fine in the iPad, but is dog slow on an iPhone 3GS, I'm hoping fixing this memory leak might speed it up a little...

This is the method that creates self.aFinals, which is passed a string from a text input. I've ommitted some of the lines but self.aFinals doesn't interact with them

-(id)initWithTerm:(NSString *)thisTerm {
    ...
    ...
    self.aFinals = [[NSMutableArray alloc] init];

    return self;
}

Then I have about 5 nested loops, that call addPlateToFinals 3 times in the middle of all the loops, creating thisPlate, which becomes sPlateToAdd

// replace 1st occurance
NSString *thisPlate = [thisBase
    stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:
        @"(^[^%@]+)%@(.*$)", 
        thisChar, 
        thisChar] 
     withString:[NSString stringWithFormat:@"$1%@$2", thisSub]
     ];

     [self addPlateToFinals:thisPlate withSubCount:thisSubCount];
 // replace 2nd occurance
 thisPlate = [thisBase
     stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:
         @"(^[^%@]+%@.*)%@",    
         thisChar, 
         thisChar, 
         thisChar] 
     withString:[NSString stringWithFormat:@"$1", thisSub]
     ];

 // then it does it again, with slightly different regex

This is the complete method that the leak is coming from:

-(void)addPlateToFinals:(NSString *)sPlateToAdd withSubCount:(NSNumber *)nSubCount {
// plate must be less than 7 characters and great than 2 chars
if (
    [sPlateToAdd length] <= [self.nPlateMax intValue] &&
    [sPlateToAdd length] >= [self.nPlateMin intValue]
    ) {    

    NSMutableArray *aSearchFinals = [self arrayOfFinals];

    // add plate if it is not already in the finals array   
    if(![aSearchFinals containsObject:sPlateToAdd]) {

        // filter out results that cannot be converted to valid plates
        NSPredicate *potential = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{0,3}[0-9]{1,3}[a-z]{0,3}

}

"]; NSPredicate *impossible1 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2,3}[a-z]{2}

}

"]; NSPredicate *impossible2 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z][0-9]{3}

}

"]; NSPredicate *impossible3 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[a-z]{2}[0-9]{2}

}

"]; NSPredicate *impossible4 = [NSPredicate predicateWithFormat: @"SELF MATCHES '^[0-9]{2}[a-z]{2}

}

"]; if( [potential evaluateWithObject: sPlateToAdd] && ![impossible1 evaluateWithObject: sPlateToAdd] && ![impossible2 evaluateWithObject: sPlateToAdd] && ![impossible3 evaluateWithObject: sPlateToAdd] && ![impossible4 evaluateWithObject: sPlateToAdd] ){ NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil]; NSArray *objects = [NSArray arrayWithObjects: sPlateToAdd, [[[NSNumber alloc] initWithInt:1] autorelease], [[[NSNumber alloc] initWithInt:1] autorelease], nil ]; NSDictionary *dPlateToAdd = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; [self.aFinals addObject:dPlateToAdd]; } } }

}

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

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

发布评论

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

评论(3

三五鸿雁 2024-12-13 01:30:09

您可能会发生此对象的内存泄漏,而此代码根本不负责。

当对象保留的时间多于释放的时间时,Cocoa/Cocoa Touch 环境中就会发生内存泄漏。这些工具将指出它是在哪里分配的,而不是在哪里泄漏的,因为这些工具无法确定哪个保留丢失了发布。它们只是保留和释放;除了惯例之外,没有什么真正将它们联系在一起。

首先,进行构建和构建分析。这可能会指出您的代码在哪里做了不正确的事情导致了泄漏。认真对待分析器警告,尤其是与内存管理相关的警告。

如果构建&分析并不能解决您的问题,请再次分析您的应用程序并研究泄漏块的历史记录。这将显示每次该块被保留或释放的时间。查找没有相应释放或自动释放的保留。 (实际上,您可能会发现,在没有 Instruments 的情况下,简单地通读代码、查找不平衡的保留会更容易。)

You may have a memory leak of this object without this code being responsible at all.

A memory leak in the Cocoa/Cocoa Touch environment happens when an object is retained more than it's released. The tools will point out where it was allocated, not where it was leaked, because the tools have no way to determine which retain is missing a release. They're just retains and releases; nothing really ties them together but conventions.

First, do a Build & Analyze. This might point out where your code is doing something improper causing a leak. Treat Analyzer warnings seriously, especially if they're related to memory management.

If Build & Analyze doesn't fix your problem, profile through your app again and study the history of the leaked block. This will show you each time the block was retained or released. Look for retains without a corresponding release or autorelease. (You may actually find it easier to simply read through your code, looking for unbalanced retains, without Instruments.)

吃兔兔 2024-12-13 01:30:09

如果可能的话,您应该使用 NSDictonary 而不是 NSMutableDictonary,因为对象的可变版本比不可变版本占用更多内存。另外,我对代码做了一些修饰增强

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil];
NSArray *objects  = [NSArray arrayWithObjects:sPlateToAdd,
                    [NSNumber numberWithInt:1], 
                    [NSNumber numberWithInt:1], 
                    nil];

NSDictonary *dPlateToAdd = [NSDictonary dictionaryWithObjects:objects forKeys:keys];  // 93.4%        
[self.aFinals addObject:dPlateToAdd];    // 6.6%

You should use NSDictonary instead of NSMutableDictonary if it is possible, because mutable versions of the objects take more memory than immutable. Also, I have done some cosmetic enhancements to the code

NSArray *keys = [NSArray arrayWithObjects:@"text", @"score", @"subCount", nil];
NSArray *objects  = [NSArray arrayWithObjects:sPlateToAdd,
                    [NSNumber numberWithInt:1], 
                    [NSNumber numberWithInt:1], 
                    nil];

NSDictonary *dPlateToAdd = [NSDictonary dictionaryWithObjects:objects forKeys:keys];  // 93.4%        
[self.aFinals addObject:dPlateToAdd];    // 6.6%
笑看君怀她人 2024-12-13 01:30:08

您应该显示整个“addPlateToFinals”方法,sPlateToAdd 可能会泄漏。

根据新添加的代码,如果使用保留声明该属性,self.aFinals 就会泄漏(我%99确实如此)。应该是:

self.aFinals = [[[NSMutableArray alloc] init] autorelease]

甚至更好:

self.aFinals = [NSMutableArray array]

You should show the entire `addPlateToFinals' method, sPlateToAdd could be leaking.

Based on the new added code self.aFinals is leaking if the property is declared with retain(and I'm %99 it is). Should be:

self.aFinals = [[[NSMutableArray alloc] init] autorelease]

or even better:

self.aFinals = [NSMutableArray array]

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