2011-04-16 5 views
0

Dans mon application, j'ai eu des fuites de mémoire dans NSMutableArray, NSArray et NSString.Fuite de mémoire dans NSMutableArray, NSArray, NSString dans iPhone SDK

Voici le code.

NSString *subQuery = [NSString stringWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];   
    [subArray addObjectsFromArray:subArray1]; 

    NSString *columnQuery = [NSString stringWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; 
    [langArray addObjectsFromArray:newArray]; 

    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",lblshortName.text]]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 

      [tempArray addObject:[NSString stringWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSString *detail = @"_________________"; 

     for (int j=0; j<[lableNameArray count]; j++) { 

      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",[lableNameArray objectAtIndex:j]]]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       detail = [NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]; 
      }    
     } 
     [detailTextArray addObject:detail]; 

    } 

Quand je cours dans Instruments je suis arrivé fuites dans

-subArray1 en deuxième ligne.

-détail (NSString) dans la seconde pour la boucle.

Et subArray et langArray sont mes tableaux globaux.

Si je supprime mutableCopy de NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; et NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; alors subArray et langArray ne retiennent pas les valeurs.

Comment éviter les fuites de mémoire dans ce code?

+0

Qu'est-ce que '-returnExecuteQuery:' faire? Renvoie-t-il un objet possédé ou non? Est-ce que son contrat dit quelque chose sur la validité de la valeur de retour pour plusieurs appels? –

+0

Est-ce que vous libérez tempArray? où? En outre, essayez de libérer subArray1 et newArray (au lieu de les libérer) après le addObjectsFromArray. – Sefran2

+0

@Fran: J'ai essayé de libérer les deux tableaux après la boucle principale, mais cela me donne l'erreur EXEC_BAD_ACCESS pour subArray et langArray. – Meghan

Répondre

1

Olease essayer celui-ci, dans le code ci-dessus, vous créez deux objets qui appartiennent à la liste de libération automatique ici est une version où j'ai essayé de gérer la libération de ces variables de chaîne.

Deuxièmement, c'est que la fuite de detail est parce que vous êtes le référencer plusieurs fois dans votre code. Et pour voir le subArray1 s'il vous plaît commentaire

NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    // please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ; 
    [subArray addObjectsFromArray:subArray1]; 

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ; 
    [langArray addObjectsFromArray:newArray]; 
    [columnQuery relese]; 
    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:@"%@",lblshortName.text]]; 


     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey]; 
     [tempKey release]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
      NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 

      [tempArray addObject:tempString]; 
      [tempString release]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSMutableString *detail = nil; 

     for (int j=0; j<[lableNameArray count]; j++) 
     { 
      detail = [[ NSMutableString alloc]initWithString:@"_________________"]; 
      NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]]; 
      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; 
      [key release]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 
      } 
       [detailTextArray addObject:detail]; 
       [detail release];    
     } 


    } 
    [subArray1 release]; 
    [newArray release]; 

UPDATE: S'il vous plaît ne pas lire les commentaires dans le code et y répondre en arrière afin que les choses pourraient être améliorées.

NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ; 
    [subArray addObjectsFromArray:subArray1]; 

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ; 
    [langArray addObjectsFromArray:newArray]; 
    [columnQuery relese]; 
    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:@"%@",lblshortName.text]]; 


     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey]; 
     [tempKey release]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
      NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 

      [tempArray addObject:tempString]; 
      [tempString release]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSMutableString *detail = [[ NSMutableString alloc]initWithString:@"_________________"]; 

     for (int j=0; j<[lableNameArray count]; j++) 
     { 

      NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]]; 
      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray? 
      [key release]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 
       break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and add it to array? 
      } 

     } 
     [detailTextArray addObject:detail]; 
     [detail release];    

    } 
    [subArray1 release]; 
    [newArray release]; 

MISE À JOUR 2:

if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail appendFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 

      } 

Merci,

+0

Merci pour le code, mais il y a encore quelques problèmes, je veux ajouter '[detailTextArray addObject: detail]; [detail release]; 'après la boucle, cela indique une fuite dans' detail'. subArray1 et newArray montrent toujours une fuite dans Instruments. – Meghan

+0

S'il vous plaît voir ci-dessus le code et aussi répondre aux commentaires dans le code afin que le scénario pourrait être plus cleare. merci – Ravin

+0

Dans les premier et deuxième commentaires: Les tableaux sont autorelease. et Troisième commentaire: Je vérifie la condition pour les valeurs nulles ou vides. Si checknull n'est pas vide ou null, il doit ajouter une chaîne de détails avec '\ n'. Pour que je puisse l'afficher dans le texte détaillé de la cellule. – Meghan

1

Vous ne savez pas ce qui cause la fuite de mémoire, mais cela peut aider. Ceci est une façon plus directe de la copie des tableaux, et peut entraîner d'éviter la fuite:

NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES]; 

Cela fait essentiellement une copie en profondeur d'un niveau du tableau retourné par returnExecuteQuery. Vous pouvez lire à ce sujet plus en détail dans Collections Programming Topics.

Je ne sais pas comment fonctionne mutableCopy et cela peut avoir quelque chose à voir avec la fuite. S'il copie les objets dans l'ancien tableau & puis les ajoute au nouveau tableau, ils peuvent entrer dans le tableau avec un nombre de retenues de 2 (1 de la copie, et 1 d'être ajouté à un tableau.) Il ne fait pas beaucoup de sens que cela devrait fonctionner de cette façon. Mais, si c'est le cas, cela pourrait expliquer la fuite.

+0

@ salo.dm: Merci pour votre répondre. Cela m'aide dans certains cas. Il montre toujours une fuite dans 'detail',' subArray1' et 'newArray'. – Meghan

+0

Si vous utilisez ce code, vous n'aurez pas besoin de newArray. Vous pouvez supprimer la ligne entière en référence à newArray. De même, vous pouvez supprimer subArray1 en remplaçant les 2ème et 3ème lignes de votre code par ce qui suit: NSArray * subArray = [[NSArray alloc] initWithArray: [self returnExecuteQuery: sous-requête] copyItems: YES]; –

+0

dm: chaque fois que cette méthode appelle, elle ajoute un nouveau buch de données dans langArray. donc cela ne m'aidera pas – Meghan

0

Vous pourriez commencer par libérer votre tempArray une fois terminé (après les boucles). Souvent, les fuites de niveau supérieur sont cachées dans le flot des fuites de niveau inférieur (c'est-à-dire que la fuite d'un conteneur provoque la fuite de tout son contenu), ce qui pourrait être le cas pour votre chaîne.

En utilisant mutableCopy] autorelease]; est très bien d'ailleurs.

Questions connexes