Утечки памяти - Objective-C - PullRequest
       3

Утечки памяти - Objective-C

0 голосов
/ 11 января 2011

Может кто-нибудь помочь указать на утечки памяти? Я получаю кучу в этом методе, и я не уверен, как именно это исправить.

- (NSMutableArray *)getTop5AndOtherKeysAndValuesFromDictionary:(NSMutableDictionary *)dict {
    NSLog(@"get top 5");
    int sumOfAllValues = 0;

    NSMutableArray *arr = [[[NSMutableArray alloc] init] retain];

    for(NSString *key in dict){
        NSString *value = [[dict objectForKey:key] retain];
        [arr addObject:value];
        sumOfAllValues += [value intValue];
    }

    //sort values
    NSArray *sorted = [[arr sortedArrayUsingFunction:sort context:NULL] retain];

    [arr release];

    //top 5 values
    int sumOfTop5 = 0;
    NSMutableArray *top5 = [[[NSMutableArray alloc] init] retain];
    for(int i = 0; i < 5; i++) {
        int proposedIndex = [sorted count] - 1 - i;
        if(proposedIndex >= 0) {
            [top5 addObject:[sorted objectAtIndex:([sorted count] - i - 1)]];
            sumOfTop5 += [[sorted objectAtIndex:([sorted count] - i - 1)] intValue];
        }
    }

    [sorted release];

    //copy of all keys
    NSMutableArray *copyOfKeys = [[[NSMutableArray alloc] init] retain];
    for(NSString *key in dict) {
        [copyOfKeys addObject:key];
    }


    //copy of top 5 values
    NSMutableArray *copyOfTop5 = [[[NSMutableArray alloc] init] retain];
    for(int i = 0; i < [top5 count]; i++) {
        [copyOfTop5 addObject:[top5 objectAtIndex:i]];
    }


    //get keys with top 5 values
    NSMutableArray *outputKeys = [[[NSMutableArray alloc] init] retain];
    for(int i = 0; i < [top5 count]; i++) {
        NSString *targetValue = [top5 objectAtIndex:i];
        for(int j = 0; j < [copyOfKeys count]; j++) {
            NSString *key = [copyOfKeys objectAtIndex:j];
            NSString *val = [dict objectForKey:key];
            if([val isEqualToString:targetValue]) {
                [outputKeys addObject:key];
                [copyOfKeys removeObjectAtIndex:j];
                break;
            }
        }
    }


    [outputKeys addObject:@"Other"];
    [top5 addObject:[[NSString stringWithFormat:@"%d",(sumOfAllValues - sumOfTop5)] retain]];


    NSMutableArray *output = [[NSMutableArray alloc] init];
    [output addObject:outputKeys];
    [output addObject:top5];

    NSMutableArray *percents = [[NSMutableArray alloc] init];
    int sum = sumOfAllValues;
    float leftOverSum = sum * 1.0f;

    int count = [top5 count];
    float val1, val2, val3, val4, val5;
    if(count >= 1)
        val1 = ([[top5 objectAtIndex:0] intValue] * 1.0f)/sum;
    else
        val1 = 0.0f;

    if(count >=2)
        val2 = ([[top5 objectAtIndex:1] intValue] * 1.0f)/sum;
    else
        val2 = 0.0f;

    if(count >= 3)
        val3 = ([[top5 objectAtIndex:2] intValue] * 1.0f)/sum;
    else
        val3 = 0.0f;

    if(count >= 4)
        val4 = ([[top5 objectAtIndex:3] intValue] * 1.0f)/sum;
    else
        val4 = 0.0f;

    if(count >=5)
        val5 = ([[top5 objectAtIndex:4] intValue] * 1.0f)/sum;
    else
        val5 = 0.0f;


    if(val1 >= .00001f) {
        NSMutableArray *a1 = [[NSMutableArray alloc] init];
        [a1 addObject:[outputKeys objectAtIndex:0]];
        [a1 addObject:[top5 objectAtIndex:0]];
        [a1 addObject:[NSString stringWithFormat:@"%.01f",(val1*100)]];
        [percents addObject:a1];
        leftOverSum -= ([[top5 objectAtIndex:0] intValue] * 1.0f);
    }
    if(val2 >= .00001f) {
        NSMutableArray *a2 = [[NSMutableArray alloc] init];
        [a2 addObject:[outputKeys objectAtIndex:1]];
        [a2 addObject:[top5 objectAtIndex:1]];
        [a2 addObject:[NSString stringWithFormat:@"%.01f",(val2*100)]];
        [percents addObject:a2];        
        leftOverSum -= ([[top5 objectAtIndex:1] intValue] * 1.0f);
    }
    if(val3 >= .00001f) {
        NSMutableArray *a3 = [[NSMutableArray alloc] init];
        [a3 addObject:[outputKeys objectAtIndex:2]];
        [a3 addObject:[top5 objectAtIndex:2]];
        [a3 addObject:[NSString stringWithFormat:@"%.01f",(val3*100)]];
        [percents addObject:a3];        
        leftOverSum -= ([[top5 objectAtIndex:2] intValue] * 1.0f);
    }
    if(val4 >= .00001f) {
        NSMutableArray *a4 = [[NSMutableArray alloc] init];
        [a4 addObject:[outputKeys objectAtIndex:3]];
        [a4 addObject:[top5 objectAtIndex:3]];
        [a4 addObject:[NSString stringWithFormat:@"%.01f",(val4*100)]];
        [percents addObject:a4];        
        leftOverSum -= ([[top5 objectAtIndex:3] intValue] * 1.0f);
    }
    if(val5 >= .00001f) {
        NSMutableArray *a5 = [[NSMutableArray alloc] init];
        [a5 addObject:[outputKeys objectAtIndex:4]];
        [a5 addObject:[top5 objectAtIndex:4]];
        [a5 addObject:[NSString stringWithFormat:@"%.01f",(val5*100)]];
        [percents addObject:a5];        
        leftOverSum -= ([[top5 objectAtIndex:4] intValue] * 1.0f);
    }

    float valOther = (leftOverSum/sum);
    if(valOther >= .00001f) {
        NSMutableArray *a6 = [[NSMutableArray alloc] init];
        [a6 addObject:[outputKeys objectAtIndex:5]];
        [a6 addObject:[top5 objectAtIndex:5]];
        [a6 addObject:[NSString stringWithFormat:@"%.01f",(valOther*100)]];
        [percents addObject:a6];    
    }

    [output addObject:percents];

    NSLog(@"mu - a");
    //[arr release];
    NSLog(@"mu - b");
    //[copyOfKeys release];
    NSLog(@"mu - c");
    //[copyOfTop5 release];
    NSLog(@"mu - c");
    //[outputKeys release];
    //[top5 release];
    //[percents release];

    return output;  
}

Ответы [ 5 ]

6 голосов
/ 11 января 2011

1.

NSMutableArray *arr = [[[NSMutableArray alloc] init] retain];

Существует только несколько способов явного увеличения 1 в управлении памятью target-c, таких как выделение, сохранение, копирование, получение, новое.Если вы используете какой-либо из них, вы должны выпустить в будущем.Вы использовали «alloc» и «retain» для одной и той же переменной «arr».

2.

NSString *value = [[dict objectForKey:key] retain];
[arr addObject:value];
sumOfAllValues += [value intValue];

Вам не нужно «сохранять» там.Также после того, как вы добавите значение в массив «arr», «arr» освободит все элементы ALL, когда «arr» будет выпущен вами.Поэтому, если вы хотите сохранить «оставьте» его, вам нужно [значение release] в последней строке цикла for.

3.

NSArray *sorted = [[arr sortedArrayUsingFunction:sort context:NULL] retain];

Опять же, вы этого не сделаетенужно "сохранить".Если вы только напишите [arr sortedArrayUsingFunction: sort context: NULL], тогда он автоматически выдаст объект с опцией autorelease.Так что вам не нужно заботиться об «выпуске» в будущем.

У всех остальных в вашем коде есть проблема, аналогичная этим первым трем.Просто убедитесь, что

1.Если вы использовали одно из: alloc, retain, attain, copy, new, mutableCopy и т. Д., Вы должны выпустить в будущем.

2.NSArray и NSMutableArray выпустят их элементы, когда вы отпустите их.Поэтому после того, как вы добавили какой-либо объект и вам не нужно ссылаться на эту переменную, его лучше освобождать после добавления в массив.Другие сборщики или контейнеры работают таким же образом.

3.Точно так же, если вы добавляете какой-либо экземпляр UIView как подпредставление в суперпредставление, то это суперпредставление будет заботиться об управлении памятью своих подпредставлений.Другими словами, если вы отпустите суперпредставление, его подпредставления будут автоматически освобождены.

Редактировать:

4.«retain» используется для увеличения внутреннего счетчика объекта.Обычно он используется в методе установки, чтобы передать право владения старой переменной новой переменной.Таким образом, вы почти никогда не используете «сохранить» при создании нового экземпляра.

Пожалуйста, исправьте меня, если я ошибаюсь!

2 голосов
/ 11 января 2011

Я знаю, что это не получит никаких голосов, так как это не дает конкретного ответа на ваш вопрос. Тем не менее, это будет лучший совет, который вы получите. Получить себе отличный профилировщик для Objective-C на Mac. Вы никогда больше не будете публиковать подобные вопросы в SO, и это поможет вам понять, что в вашем коде неправильно. Я не говорю языком по щеке. Серьезно, никто здесь не должен пытаться анализировать ваш код на предмет утечек памяти. Есть люди, которые посвящают свою карьеру разработке программного обеспечения, чтобы сделать это для вас.

0 голосов
/ 11 января 2011

начните со статического анализатора - там есть лот .статический анализатор с уловом многих из них.

0 голосов
/ 11 января 2011

Было бы очень полезно, если бы вы упомянули, какие объекты вы пропускаете.Кроме того, я подозреваю, что прогон «построить и проанализировать» проведет вас через многие, если не все, из них.

Например, [[[NSMutableArray alloc] init] retain] дает вам объект, на котором у вас есть два объекта.Похоже, это не то, что вы ожидаете.

См. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

Вы вступаете во владение объектом, если создаете его, используя метод, имя которого начинаетсяс помощью «alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy), или если вы отправите ему сообщение сохранения.

0 голосов
/ 11 января 2011

Очевидно, что в вашем коде обязательно должны быть утечки. Почему вы продолжаете сохранять массив Mutable при каждой его инициализации?

Вы должны попытаться обнаружить утечку памяти с помощью CLANG (статический анализатор). Вы можете сделать это, набрав cmd + shift + A в своем окне кода.

Приветствия

...