Утечка памяти iOS в соответствии с инструментами - PullRequest
1 голос
/ 21 сентября 2011

Screen shot of memory leak in instruments

Пожалуйста, помогите! Я прочитал правила управления памятью, но, может быть, мне не хватает их указания где-то. 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%

массивы ключей и объектов не выделяются и не инициализируются, поэтому я не думаю, что мне нужно их освобождать?

Тогда числа внутри Объектов автоматически высвобождаются, так что они в порядке, не так ли? И 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];   
        }
    }
}

}

Ответы [ 3 ]

3 голосов
/ 21 сентября 2011

Вы должны показать весь метод `addPlateToFinals ', sPlateToAdd может просочиться.

На основании нового добавленного кода self.aFinals происходит утечка, если свойство объявлено с сохранением (и я% 99, это так). Должно быть:

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

или даже лучше:

self.aFinals = [NSMutableArray array]

0 голосов
/ 21 сентября 2011

У вас может быть утечка памяти этого объекта, если этот код вообще не отвечает.

Утечка памяти в среде Cocoa / Cocoa Touch происходит, когда объект удерживается больше, чем освобождается.Инструменты будут указывать, где он был размещен, а не где он просочился, потому что инструменты не могут определить, в каком хранилище отсутствует версия.Они просто сохраняют и выпускают;ничто не связывает их воедино, кроме соглашений.

Сначала сделайте Build & Analyze.Это может указывать, где ваш код делает что-то неправильное, что приводит к утечке.Относитесь к предупреждениям Analyzer серьезно, особенно если они связаны с управлением памятью.

Если Build & Analyze не устранил вашу проблему, снова выполните профилирование в вашем приложении и изучите историю утечки блока.Это будет отображаться каждый раз, когда блок был сохранен или освобожден.Ищите сохранения без соответствующего выпуска или авто-выпуска.(На самом деле, вам может оказаться проще просто прочитать ваш код в поисках несбалансированных остатков без инструментов.)

0 голосов
/ 21 сентября 2011

Вы должны использовать 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%
...