2011-01-11 5 views
0

Quelqu'un peut-il aider à signaler les fuites de mémoire? Je reçois un tas dans cette méthode et je ne suis pas sûr exactement comment y remédier.Fuites de mémoire - Objective-C

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

Répondre

6

1.

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

Il n'y a que quelques façons d'incrémenter explicitement 1 dans la gestion de la mémoire objective-c tels que alloc, conserver, copier, atteindre, nouveau. Si vous utilisez l'un de ces éléments, vous devez le publier ultérieurement. Vous avez utilisé "alloc" et "retain" pour la même variable "arr".

2.

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

Vous n'êtes pas obligé de "conserver" là. Aussi, après avoir ajouté une valeur à un tableau "arr", "arr" va libérer ses éléments ALL lorsque "arr" est publié par vous. Donc, si vous voulez garder "conserver", vous devez [release release] dans la dernière ligne de cette boucle for.

3.

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

Encore une fois, vous n'avez pas besoin de "conserver". Si vous écrivez seulement [arr sortedArrayUsingFunction: tri contexte: NULL], alors il donnera automatiquement un objet avec option autorelease. Vous n'avez donc pas à vous soucier de "libérer" à l'avenir.

Tous les autres dans votre code ont un problème similaire à ces trois premiers.Assurez-vous simplement

1. Si vous avez utilisé l'un des mots clés "alloc", "retain", "reach", "copy", "new", "mutableCopy", etc., vous devez les publier ultérieurement.

2. NSArray et NSMutableArray publient leurs éléments lorsque vous les libérez. Donc, après avoir ajouté un objet et que vous n'avez pas besoin de vous référer à cette variable, il est préférable de le relâcher après l'ajout à un tableau. D'autres collecteurs ou conteneurs fonctionnent de la même manière. De même, si vous ajoutez une instance de UIView en tant que sous-vue à superview, alors cette vue en majuscule prendra soin de la gestion de la mémoire de ses sous-vues. En d'autres termes, si vous publiez superview, ses sous-vues seront automatiquement libérées.

Edit:

4. "conserver" est utilisé pour incrémenter un compteur interne d'un objet. Habituellement, il est utilisé dans une méthode setter pour donner une propriété d'une ancienne variable à une nouvelle variable. Ainsi, vous n'utilisez presque jamais "retenez" lorsque vous créez une nouvelle instance.

S'il vous plaît, corrigez-moi si je me trompe!

+3

Je suis +1 parce que vous avez réellement parcouru son code et essayé d'expliquer pourquoi il est faux. Une chose que je suggérerais FORTEMENT pour l'avenir de cette question est d'expliquer quand un développeur veut retenir. Il a fait l'erreur de l'utiliser, ce qui signifie que son utilisation n'était pas claire. Si vous pouvez modifier votre réponse avec une heure et un lieu à retenir, je crois que vous serez la réponse acceptée. –

0

De toute évidence, il y a forcément des fuites dans votre code.Why gardez-vous de vous retenir Mutable tableau chaque fois que vous l'initialiser?

Vous devriez essayer de trouver votre fuite de mémoire à l'aide de CLANG (analyseur statique). Vous pouvez le faire en tapant cmd + shift + A dans votre fenêtre de code.

Vive

+0

Je ne l'avais pas déjà là-bas, et ça me donnait toujours des fuites. Devrait-il n'y avoir aucune retenue? – CodeGuy

+0

Sauf si et jusqu'à ce qu'il soit largement requis, ne retenez rien, sauf si vous libérez une variable son nombre de retenue est 1 une fois initialisé. – Aditya

+0

Mais pourquoi est-ce que quand j'ai un NSMutableDictionary (\t déclaré de cette façon: NSMutableDictionary * output = [[[NSMutableDictionary alloc] init] autorelease];) et puis j'ai le code: \t \t \t NSString * temp = [NSString stringWithFormat: @ "% d", val]; [Output setValue: temp forKey: source] ;, Je reçois des fuites de mémoire. – CodeGuy

0

début avec l'analyseur statique - il y a un beaucoup là-dedans. l'analyseur statique avec beaucoup d'entre eux.

+1

et je vous recommande de lire la documentation concernant la gestion de la mémoire de cacao. Les règles sont relativement simples et vous ne pouvez pas vous permettre de vous tromper. – justin

0

Il serait vraiment utile si vous deviez mentionner quels objets vous fuyez. De plus, je soupçonne qu'une série de «construire et analyser» vous guidera à travers beaucoup, sinon tous, d'entre eux.

Par exemple [[[NSMutableArray alloc] init] retain] vous donne un objet que vous possédez deux conserve. Cela ne semble pas être ce que vous attendez de lui.

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

Vous prenez possession d'un objet si vous créez à l'aide d'une méthode dont le nom commence par « alloc » ou « nouveau » ou contient « copie » (par exemple, alloc, newObject, ou mutableCopy), ou si vous lui envoyez un message de conservation.

2

Je sais que cela n'obtiendra pas de votes, car il ne répond pas spécifiquement à votre question. Néanmoins, ce sera le meilleur conseil que vous obtiendrez. Procurez-vous un excellent profileur pour Objective-C sur le mac. Vous ne poserez plus jamais une question comme celle-ci sur SO et cela vous éclairera sur toutes les choses qui ne vont pas dans votre code. Je ne suis pas la langue dans la joue. Sérieusement, personne ici ne devrait essayer d'analyser votre code pour les fuites de mémoire. Il y a des gens qui consacrent leur carrière au développement de logiciels pour le faire pour vous.