简体   繁体   English

内存泄漏-Objective-C

[英]Memory Leaks - Objective-C

Can anyone help point out memory leaks? 谁能帮助指出内存泄漏? I'm getting a bunch within this method and I'm not sure exactly how to fix it. 我在这种方法中遇到了很多问题,我不确定到底该如何解决。

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

1. 1。

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

There are only few ways to explicitly increment 1 in objective-c's memory management such as alloc, retain, copy, attain, new. 在objective-c的内存管理中,只有几种方法可以显式地递增1,例如分配,保留,复制,获取,新建。 If you use any of these, you must release in the future. 如果使用其中任何一种,则将来必须释放。 You used "alloc" and "retain" to the same variable "arr". 您将“ alloc”和“ retain”用于相同的变量“ arr”。

2. 2。

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

You don't need to "retain" there. 您无需在此“保留”。 Also after you add value to an array "arr", "arr" will release its ALL elements when "arr" is released by you. 同样,在向数组“ arr”添加值之后,当您释放“ arr”时,“ arr”将释放其所有元素。 So if you want to keep "retain" it, you have to [value release] in the last line of this for loop. 因此,如果要保留“保留”它,则必须在此for循环的最后一行中[值释放]。

3. 3。

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

Again, you don't need to "retain." 同样,您不需要“保留”。 If you only write [arr sortedArrayUsingFunction:sort context:NULL], then it will automatically gives an object with autorelease option. 如果仅编写[arr sortedArrayUsingFunction:sort context:NULL],则它将自动为对象提供autorelease选项。 So you don't have to care about "release" in the future. 因此,您将来不必担心“释放”。

All others in your code have similar problem to these first three. 您代码中的所有其他代码与前三个代码都有类似的问题。 Just make sure 只要确保

1. If you used one of "alloc", "retain", "attain", "copy", "new", "mutableCopy" and so on, you must release in the future. 1.如果您使用了“ alloc”,“ retain”,“ attain”,“ copy”,“ new”,“ mutableCopy”等之一,则将来必须释放。

2. NSArray and NSMutableArray will release their elements when you release them. 2. NSArray和NSMutableArray将在释放它们时释放它们的元素。 So after you add any object and don't need to refer by that variable, then it's better to release after adding to an array. 因此,在添加任何对象并且不需要通过该变量引用之后,最好在添加到数组后释放它。 Other collectors or containers work in the same way. 其他收集器或容器以相同的方式工作。

3. Similarly, if you add any UIView instance as a subview to superview, then that superview will care its subviews' memory management. 3.同样,如果您将任何UIView实例作为子视图添加到超级视图,则该超级视图将负责其子视图的内存管理。 In other words, if you release superview, its subviews will automatically be released. 换句话说,如果您释放超级视图,则其子视图将自动释放。

Edit: 编辑:

4. "retain" is used to increment an internal counter of an object. 4.“保留”用于增加对象的内部计数器。 Usually, it's used in a setter method to give an ownership from an old variable to a new variable. 通常,它用在setter方法中,以将旧变量赋予新变量的所有权。 So, you almost never use "retain" when you create a new instance. 因此,创建新实例时几乎几乎不会使用“保留”。

Please, correct me if I'm wrong! 请纠正我,如果我错了!

I know this won't get any up votes as it doesn't specifically answer your question. 我知道这不会获得任何支持,因为它没有具体回答您的问题。 Nonetheless it will be the best piece of advice you will get. 尽管如此,这将是您获得的最佳建议。 Get yourself a great profiler for Objective-C on the mac. 在Mac上让自己成为出色的Objective-C分析器。 You will never post a question like this again on SO and it will enlighten you to all the things wrong within your code. 您将再也不会在SO上发布这样的问题,它将启发您代码中的所有错误。 I am not being tongue in cheek. 我不是在脸颊上吐舌。 Seriously no one here should try to analyze your code for memory leaks. 严重的是,这里没有人应该尝试分析您的代码是否存在内存泄漏。 There are people that dedicate their careers on developing software to do this for you. 有些人致力于开发软件来为您做到这一点。

Obviously there are bound to be leaks in your code.Why do you keep on retaining you Mutable array every time you initialize it? 显然您的代码中肯定会存在泄漏。为什么每次初始化时都继续保留Mutable数组?

You should try to find out your memory leak with the help of CLANG(static analyzer).You can do it by typing cmd+shift+A in your code window. 您应该尝试在CLANG(静态分析器)的帮助下找出内存泄漏。您可以通过在代码窗口中键入cmd + shift + A来实现。

Cheers 干杯

start with the static analyzer - there's a lot in there. 从静态分析仪开始-里面有很多东西。 the static analyzer with catch many of them. 静态分析仪捕获了很多。

It would really help if you were to mention which objects you are leaking. 如果您要提及泄漏的对象,那将真的有帮助。 In addition I suspect that a "build and analyze" run would walk you through many, if not all, of them. 另外,我怀疑“构建和分析”运行会引导您完成许多(如果不是全部)的过程。

For example [[[NSMutableArray alloc] init] retain] gives you an object you own two retains on. 例如, [[[NSMutableArray alloc] init] retain]给您一个拥有两个保留对象的对象。 That doesn't seem to be what you are expecting it to do. 这似乎不是您期望的那样。

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

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. 如果使用名称以“ alloc”或“ new”开头或包含“ copy”(例如alloc,newObject或mutableCopy)的方法创建对象,或者向其发送保留消息,则您拥有该对象的所有权。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM