Memory Leak NSMutableArray

NigokiNigoki Membre
05:24 modifié dans API UIKit #1
Salut, c'est encoire moi  :kicking:

Alala la gestion de la mémoire, quelle belle invention  ;D

Grâce au logiciel CLANG GUI j'ai pu identifier les trois quarts de mes problèmes que me signalait l'instrument memory leak du SDK.

J'avoue que j'ai pas encore tout compris sur les nonatomic et retain, mais j'ai pigé le 1 alloc = 1 release.

Cependant j'ai encore besoin de vos lumières  :why?: (qui a dit assisté ?  :fouf):)

Dans mon code si dessous :
<br />Message *message = nil;<br />while(...) {<br /> <br />message = [[Message alloc] initWithDatabaseRow:statement];<br />[tab addObject:message];<br />[message release];<br /> <br />}<br />


Je construit mon objet Message et hop je le met dans le tableau... C'est tout beau sauf que instruments me dit que mon objet Message n'est jamais release.
Dans le détails j'ai bien :
malloc    16  [[Message alloc] initWithDatabaseRow:statement];
retain      0  [tab addObject:message];
release    0  [message release];

Mais que je mette release ou pas, j'ai une fuite de mémoire.

Réponses

  • muqaddarmuqaddar Administrateur
    05:24 modifié #2
    Message *message;<br />while(...) {<br /> <br />message = [[Message alloc] initWithDatabaseRow:statement];<br />[tab addObject:message];<br />[message release];<br /> <br />}
    


    Et là  ?
  • Philippe49Philippe49 Membre
    05:24 modifié #3
    Avec ce schéma, message a un retain count=1. Donc ton code est bon.
    message sera releasé, et donc désalloué, lorsque la NSMutableArray tab le sera. En effet une NSMutableArray effectue un retain sur les objets qui lui sont ajoutés, et un release lorsqu'elle est désallouée.

    Je pense donc que la fuite mémoire vient de tab, pas de message.
  • muqaddarmuqaddar Administrateur
    05:24 modifié #4
    dans 1245080711:

    Avec ce schéma, message a un retain count=1. Donc ton code est bon.
    message sera releasé, et donc désalloué, lorsque la NSMutableArray tab le sera. En effet une NSMutableArray effectue un retain sur les objets qui lui sont ajoutés, et un release lorsqu'elle est désallouée.

    Je pense donc que la fuite mémoire vient de tab, pas de message.


    Je croyais que :

    Message *message = nil;
    


    faisait aussi un retain count à  1, contrairement à  :

    Message *message;
    


    La fuite ne vient-elle pas de là  ?
  • Philippe49Philippe49 Membre
    05:24 modifié #5
    Non, Message * message=nil; ne crée aucun objet. Il fait de la variable message une référence vers nil sans aucun impact sur la mémoire.
  • muqaddarmuqaddar Administrateur
    05:24 modifié #6
    dans 1245083158:

    Non, Message * message=nil; ne crée aucun objet. Il fait de la variable message une référence vers nil sans aucun impact sur la mémoire.


    Et à  quoi cela sert dans son cas ? (juste pour info)
  • Philippe49Philippe49 Membre
    05:24 modifié #7
    En l'occurence à  rien.

    On voit souvent cette habitude de mettre à  nil les variables lors de leur déclaration. J'ai l'impression que c'est une mode. Cela peut servir pour des tests ultérieurs : if(message)
    Par exemple avec

    Message * message=nil;
    while(message==nil) {
        .....
        if( ....) {
            message=
        }
    }


  • Philippe49Philippe49 Membre
    juin 2009 modifié #8
    Essai :
    <br />#import &lt;Foundation/Foundation.h&gt;<br /><br /><br />int main (int argc, const char * argv&#91;]) {<br />	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />	NSString * string;<br />	if(string==nil) {<br />		puts(&quot;string==nil&quot;);<br />	} else {<br />		puts(&quot;string!=nil&quot;);<br />	}<br />	[pool drain];<br />	return 0;<br />}
    


    Exécution

    % gcc pgm.m -o pgm -framework Foundation
    % pgm
    string!=nil
    %



    Par ailleurs NSLog(@%@",[string class]); provoque un crash de l'appli ...
  • muqaddarmuqaddar Administrateur
    05:24 modifié #9
    dans 1245084032:

    En l'occurence à  rien.

    On voit souvent cette habitude de mettre à  nil les variables lors de leur déclaration. J'ai l'impression que c'est une mode. Cela peut servir pour des tests ultérieurs : if(message)
    Par exemple avec

    Message * message=nil;
    while(message==nil) {
        .....
        if( ....) {
            message=
        }
    }





    Merci pour l'info. Son bug doit donc bien venir de tab.
  • DrakenDraken Membre
    05:24 modifié #10
    dans 1245084032:

    En l'occurence à  rien.

    On voit souvent cette habitude de mettre à  nil les variables lors de leur déclaration. J'ai l'impression que c'est une mode. Cela peut servir pour des tests ultérieurs : if(message)
    Par exemple avec

    Message * message=nil;
    while(message==nil) {
        .....
        if( ....) {
            message=
        }
    }


    Et que contient la variable message à  la création quand elle n'est pas initialisée par nil ?



  • zoczoc Membre
    05:24 modifié #11
    dans 1245086138:

    Et que contient la variable message à  la création quand elle n'est pas initialisée par nil ?


    N'importe quoi. En gros ce qui était sur la pile d'exécution à  l'endroit ou la variable locale a été placée.
  • NigokiNigoki Membre
    05:24 modifié #12
    Oui j'initialise mes variables à  nil quand j'ai besoin de faire un test (var != nil).

    J'ai encore des lacunes sur la gestions de la mémoire :/ Même quand par exemple je fais :
    <br />self.date = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(statement, 2)];<br />
    


    ou

    <br />self.text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];<br />
    


    J'ai une fuite de mémoire. Et si j'essai un autorelease l'appli crash.
    En ce qui concerne mon poste initiale, il semble bien que le problème vienne du NSMutableArray que je release jamais et donc lui et les objets qui contient ne sont jamais libéré.

    Ce tableau me sert dans un TBVController, je fais [self.data = [DBEngine createList]] sur un viewDiDAppear.
    Du coup je peux pas faire un [self.data release]; et je sais pas trop comment m'y prendre autrement  :crackboom:-

  • zoczoc Membre
    05:24 modifié #13
    dans 1245086889:

    Oui j'initialise mes variables à  nil quand j'ai besoin de faire un test (var != nil).

    J'ai encore des lacunes sur la gestions de la mémoire :/ Même quand par exemple je fais :
    <br />self.date = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(statement, 2)];<br />
    


    ou

    <br />self.text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];<br />
    


    J'ai une fuite de mémoire. Et si j'essai un autorelease l'appli crash.


    Il ne faut évidemment pas faire de release ni d'autorelease sur les objets retournés par dateWith... et stringWith..., puisque, comme leur nom ne commencent ni par init ni par copy ou mutableCopy, tu n'es pas propriétaire de l'objet (et par conséquent, ces méthodes ont DEJA fait un autorelease).

    Par contre, il faut évidemment faire un [date release] et un [text release] dans la méthode dealloc de la classe, sous peine de leaker un NSDate et un NSString  ;)
  • Philippe49Philippe49 Membre
    juin 2009 modifié #14
    dans 1245086889:
    <br />self.text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];<br />
    


    Il faut regarder dans la doc si sqlite3_column_text() ne renvoie pas une chaà®ne allouée par malloc(), auquel cas il faut faire un free. A voir

    dans 1245086889:

    du NSMutableArray que je release jamais et donc lui et les objets qui contient ne sont jamais libéré.

    On peut libérer les éléments du tableau sans le détruire
    [...... removeAllObjects]
    Dès lors les objets ainsi détachés de la collection recevront un message release et seront détruits si leur retain count est à  1.
  • Philippe49Philippe49 Membre
    05:24 modifié #15
    dans 1245090599:

    self.text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];
    Il faut regarder dans la doc si sqlite3_column_text() ne renvoie pas une chaà®ne allouée par malloc(), auquel cas il faut faire un free. A voir

    Réponse négative : The pointers returned are valid until a type conversion occurs as described above, or until sqlite3_step() or sqlite3_reset() or sqlite3_finalize() is called. The memory space used to hold strings and BLOBs is freed automatically
  • NigokiNigoki Membre
    05:24 modifié #16
    Merci à  vous pour vos réponses complètes  :p

    En fait avoir un pic rouge sous Instruments pour le leaks n'est pas rédibitoire ? Les leaks de mes NSString ou NSDate alloué (16 bytes) avec stringWith... dateWith... sont bien indiqué comme autorealese sauf qu'on ne retrouve pas (-16 bytes). Mais à  partir du moment ou on vois bien qu'ils ont reçu l'instruction release, on peut rien faire de plus ?

    Idem j'ai des tableaux que j'init dans le viewDiDload et que je release dans le dealloc. J'ai des leak également pour ces tableaux où l'on voit 32 bytes à  la ligne de l'alloc et toujours 0 quand il passe dans le dealloc (au lieu de -32 je suppose)

    Dois je supposer que pour les leaks indiqué, si on voit bien qu'on a une instruction release sur l'objet, on y  peut rien ?  >:)
  • Philippe49Philippe49 Membre
    05:24 modifié #17
    dans 1245139838:

    En fait avoir un pic rouge sous Instruments pour le leaks n'est pas rédibitoire ? Les leaks de mes NSString ou NSDate alloué (16 bytes) avec stringWith... dateWith... sont bien indiqué comme autorealese sauf qu'on ne retrouve pas (-16 bytes). Mais à  partir du moment ou on vois bien qu'ils ont reçu l'instruction release, on peut rien faire de plus ?

    Non, il faut faire disparaà®tre les pics.

    dans 1245139838:

    Idem j'ai des tableaux que j'init dans le viewDiDload et que je release dans le dealloc. J'ai des leak également pour ces tableaux où l'on voit 32 bytes à  la ligne de l'alloc et toujours 0 quand il passe dans le dealloc (au lieu de -32 je suppose)
    Dois je supposer que pour les leaks indiqué, si on voit bien qu'on a une instruction release sur l'objet, on y  peut rien ?  >:)

    Pareil, avec une appli clean, il n'y a aucun pic dans l'instrument Leaks

    Ce post parle de la même chose
Connectez-vous ou Inscrivez-vous pour répondre.