ObjectAlloc

ancrouancrou Membre
13:44 modifié dans API AppKit #1
Bonjour,
j'ai une fuite mémoire !
J'ai surchargé retain et release dans ma classe ObjetW et mis breakpointer pour compter  combien de fois je passe.

Je passe:
24 fois dans retain
24 fois dans release
et il me reste 12 ObjetW non libérer, vu par ObjectAlloc

<br />-(id)initWithX{<br />&nbsp; &nbsp; if(self = [self init]){<br />		tab = [[NSMutableArray alloc] init ];&nbsp; // un tableau de ObjectW<br />	}<br />&nbsp; &nbsp; return self;<br />}<br />-(void) dealloc{	<br />&nbsp; &nbsp; [tab release];<br />&nbsp; &nbsp; [super dealloc];<br />}<br /><br />-(BOOL) doW{<br />	std::vector&lt;WaveHemodynamic&gt; wa;<br />	wa = glue-&gt;do();<br />	unsigned short sizeVec = wa.size();<br />	ObjectW* wave;<br />	for(unsigned short ii=0; ii&lt;sizeVec;ii++){<br />		wave = [[ObjectW alloc] initWith];<br /><br />		[tab addObject:wave];<br />		[wave release];<br />	}<br />	wa.~vector();<br />	return YES;<br />}<br />


<br />[f doW];<br />NSMutableArray* donnee = [[[NSMutableArray alloc] initWithArray:[f tab]]retain];<br /><br />ObjectW* wave;<br />		<br />for(ii=0;ii&lt;nombreii;ii++){		<br />wave = [[donnee objectAtIndex:ii]retain];<br />}<br />[donnee release];<br />[wave release];<br />


Voyez vous où j'ai oublié de libérer ?

Merci

Réponses

  • AliGatorAliGator Membre, Modérateur
    13:44 modifié #2
    Salut,

    Alors les trucs qui me choquent dans ton code :

    1) L'appel explicite au destructeur de ~vector() : c'est pas à  faire ça, et de toute façon pas nécessaire car la variable wa étant locale à  la fonction doW, elle sera détruite dès qu'elle sortira du scope où elle est déclarée, ici la fonction doW.

    2) c'est quoi cette méthode "initWith" de ta classe ObjectW ? C'est pas un nommage conventionnel ! soit c'est "init" tout court, soit c'est "initWithQQch:" avec un paramètre à  la suite...

    3) Ton NSMutableArray tu le crées avec alloc+initWithArrai+retain... le retain n'a rien à  faire là , un objet créé par alloc+init[...] est déjà  retenu une fois.
    Si tu relis la règle de base expliquée sur l'ADC,
    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. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
    Donc si tu fais un alloc, tu dois faire un release pour le balancer quand tu n'as plus besoin de l'objet. Si tu fais un retain, tu dois faire aussi un release pour balancer le retain.
    Donc si tu fais alloc+init+retain (ce qui est inutile), tu devrais donc faire deux release, un pour alloc un pour retain...
    Là  tu n'as même pas besoin du retain après alloc/init, ton objet vient d'être créé il a déjà  un retainCount de 1 !

    4) Pas besoin, au cas où c'était ce que tu voulais faire et que c'était une faute de frappe, d'envoyer un retain à  [f tab] (du moins si tu as bien codé l'accesseur de ta variable "tab"). Tu n'as à  t'occuper que des objets que tu crées (comme indiqué dans la même note de l'ADC). De ce côté sinon c'est le NSMutableArray qui s'occupe des objets que tu lui passes et qu'il gère ensuite de son côté.

    5) Tu envoies nombreii[/ii] retain à  tes objets (et je ne comprends d'ailleurs pas pourquoi, vu qu'ils sont déjà  retenus par le tableau "donnee" lui-même, aucun intérêt de leur envoyer un retain ici) alors que tu n'envoies qu'un seul "release", au dernier objet wave vers lequel tu pointes à  la fin de ta boucle. Donc il y a un déséquilibre de ce côté aussi.
  • Philippe49Philippe49 Membre
    13:44 modifié #3
    NSMutableArray* donnee = [NSMutableArray alloc] initWithArray:[f tab retain];
    fait un double retain sur donnee

    On peut sans doute le remplacer par :
    NSMutableArray* donnee = [NSMutableArray arrayWithArray:[f tab]];
    sans faire le [donnee release] final.
  • ancrouancrou Membre
    août 2008 modifié #4
    Merci, je retire les truc abusif.

    -(id)initWithX{<br />&nbsp; &nbsp; if(self = [self init]){<br />		tab = [[NSMutableArray alloc] init ];&nbsp; // un tableau de ObjectW<br />	}<br />&nbsp; &nbsp; return self;<br />}<br />-(void) dealloc{	<br />&nbsp; &nbsp; [tab release];<br />&nbsp; &nbsp; [super dealloc];<br />}<br /><br />-(BOOL) doW{<br />	std::vector&lt;WaveHemodynamic&gt; wa;<br />	wa = glue-&gt;do();<br />	unsigned short sizeVec = wa.size();<br />	ObjectW* wave;<br />	for(unsigned short ii=0; ii&lt;sizeVec;ii++){<br />		wave = [[ObjectW alloc] initWithX];<br /><br />		[tab addObject:wave];<br />		[wave release];<br />	}<br />	return YES;<br />}[/code]<br /><br /><br />[code=classe P]<br />[f doW];<br />NSMutableArray* donnee = [[NSMutableArray alloc] initWithArray:[f tab]];<br /><br />ObjectW* wave;<br />		<br />for(ii=0;ii&lt;nombreii;ii++){		<br />wave = [donnee objectAtIndex:ii];<br />}
    


    dans 1217859881:

    2) c'est quoi cette méthode "initWith" de ta classe ObjectW ? C'est pas un nommage conventionnel ! soit c'est "init" tout court, soit c'est "initWithQQch:" avec un paramètre à  la suite...

    initWith car j'ai masqué des trucs :S

    dans 1217859881:

    1) L'appel explicite au destructeur de ~vector() : c'est pas à  faire ça, et de toute façon pas nécessaire car la variable wa étant locale à  la fonction doW, elle sera détruite dès qu'elle sortira du scope où elle est déclarée, ici la fonction doW.

    le destructeur de vector, j'étais désespéré


    Mais toujours le même problème  :'(
  • ChachaChacha Membre
    13:44 modifié #5
    Un "init" augmente le compteur de référence de 1, le retain aussi.
    Dans ton premier post, wave = [[donnee objectAtIndex:ii]retain] provoque une fuite mémoire.
    Dans ton deuxième post, il manque [donnee release]

    +
    Chacha
  • ancrouancrou Membre
    13:44 modifié #6
    dans 1217862060:

    Dans ton premier post, wave = [[donnee objectAtIndex:ii]retain] provoque une fuite mémoire.

    J'ai enlevé le retain

    dans 1217862060:

    Dans ton deuxième post, il manque [donnee release]

    Si je mets un [donnee release] apres le for, ça plante  >:(
    Donc je le mets et j'enlève le [tab release] dans la méthode -(void) dealloc{

    Mais toujours le même problème 12 ObjetW non libérés, vu par ObjectAlloc
  • Philippe49Philippe49 Membre
    août 2008 modifié #7
    dans 1217858158:

    <br />[f doW];<br />NSMutableArray* donnee = [[[NSMutableArray alloc] initWithArray:[f tab]]retain];<br /><br />ObjectW* wave;<br />		<br />for(ii=0;ii&lt;nombreii;ii++){		<br /> wave = [[donnee objectAtIndex:ii]retain];<br />}<br />
    


    Il semble que tu veuilles balayer les objets de nom générique wave qui se trouve dans le NSArray tab.
    Voilà  comment je ferais :

    [f doW];
    for(ObjectW* wave in [f tab]) {
       // do anything with wave, without any retain or release
    }


    et c'est tout
  • Philippe49Philippe49 Membre
    13:44 modifié #8
    ou encore selon ce qui me semble ton esprit :

    NSMutableArray * donnee=[f tab];
    ObjectW* wave;
    NSInteger ii;
    for(ii=0;ii<nombreii;ii++){
       wave = [donnee objectAtIndex:ii];
       // do ...
    }


    et là , cela ne doit pas planter, on ne fait que renommer le pointeur sur tab .
  • ancrouancrou Membre
    13:44 modifié #9
    dans 1217863987:

    [f doW];
    for(Object* wave in [f tab]) {
       // do anything with wave, without any retain or release
    }


    et c'est tout


    ça ne compile pas :
    error: nested functions are disabled, use -fnested-functions to re-enable
    error: syntax error before 'in'
    ???
  • schlumschlum Membre
    13:44 modifié #10
    C'est parce que c'est une technique Objective-C 2.0

    Pour Objective-C 1.0, il faut utiliser NSEnumerator
  • Philippe49Philippe49 Membre
    13:44 modifié #11
    Object --> ObjectW
  • ancrouancrou Membre
    13:44 modifié #12
    dans 1217864958:

    Object --> ObjectW

    Oui, je l'avais corrigé de moi même  :P
  • ancrouancrou Membre
    13:44 modifié #13
    dans 1217864532:

    ou encore selon ce qui me semble ton esprit :

    oui, je comprends mieux  ::)

    dans 1217864532:

    NSMutableArray * donnee=[f tab];
    ObjectW* wave;
    NSInteger ii;
    for(ii=0;ii<nombreii;ii++){
       wave = [donnee objectAtIndex:ii];
       // do ...
    }


    et là , cela ne doit pas planter, on ne fait que renommer le pointeur sur tab .

    ça compile, marche ... mais toujours mes 12 ObjectW non libérés

    j'ai enlevé le [donnee release] avec cette méthode

    Je ne peux pas faire un release sur tab dans le -(void) dealloc{
    Alors que dans le init j'ai fait un alloc et init de tab  :-\\


  • Philippe49Philippe49 Membre
    août 2008 modifié #14
    dans 1217865776:

    j'ai enlevé le [donnee release] avec cette méthode

    Bien sur

    dans 1217865776:

    ça compile, marche ... mais toujours mes 12 ObjectW non libérés

    Il n'y a aucune raison qu'ils soient libérés tant que f n'est pas désalloué. Pour que les objets répertoriés dans tab disparaissent, il faut que quelque part il y ait un [f release] : la durée de vie de tab, et des objets est ici identique à  celle de f.


  • ancrouancrou Membre
    13:44 modifié #15
    dans 1217866964:

    Il n'y a aucune raison qu'ils soient libérés tant que f n'est pas désalloué. Pour que les objets répertoriés dans tab disparaissent, il faut que quelque part il y ait un [f release] : la durée de vie de tab, et des objets est ici identique à  celle de f.


    J'avais un autorelease sur f avec le alloc et init
    Je l'ai enlevé et mis un release à  la fin de l'utilisation de f.

    Mais toujours pareil.

    Donc reprenons:

    Dans la classe Inter; méthode doW
    la ligne [tab addObject:wave]; fait appel à  un retain; 12 fois (normal).
    la ligne qui suit [wave release]; fait appel à  release; 12 fois.
    Au final, il en reste 12, certainement le init => wave = [[ObjectW alloc] initWithAll:deTypeNSString:deTypeUnsignedInt];

    Dans le init de la classe inter j'ai : tab = [[NSMutableArray alloc] init ];
    Mais dans le -(void) dealloc{, je ne peut pas faire de [tab release];sinon crash


  • Philippe49Philippe49 Membre
    13:44 modifié #16
    dans 1217867949:

    Mais dans le -(void) dealloc{, je ne peut pas faire de [tab release];sinon crash

    cela peut venir de deux raisons :
    • soit tab a déjà  été desalloué  // [tab retainCount]=0
    • soit l'un au moins des objets wave a été désalloué, et lors du [tab release] un mesage release lui est envoyé.
  • ancrouancrou Membre
    13:44 modifié #17
    dans 1217868673:


    cela peut venir de deux raisons :
    • soit tab a déjà  été desalloué   // [tab retainCount]=0
    • soit l'un au moins des objets wave a été désalloué, et lors du [tab release] un mesage release lui est envoyé.



    I think so mais je ne vois pas où :S
    Quand je fais au débug:
    init de Wave
    Retain de wave
    release de wave
    cela 12 fois.
    Apres au release de la l'objet Inter, il fait appel à  son dealloc
    et donc au [tab release];
    le [tab release]; appel 12 fois le release de Wave et au 12ème crash !

    J'ai trop le démon de me faire chier sur ce truc de merde !
  • Philippe49Philippe49 Membre
    13:44 modifié #18
    Il me semble que tu avais au début de ton post

    for(ii=0;ii<nombreii;ii++){
    wave = [[donnee objectAtIndex:ii]retain];
    }
    [donnee release];
    [wave release];


    Ton [wave release] final, tu l'as toujours ?
    Parce qu'il n'a rien à  faire ici
  • ancrouancrou Membre
    13:44 modifié #19
    dans 1217869328:

    Il me semble que tu avais au début de ton post

    for(ii=0;ii<nombreii;ii++){
    wave = [[donnee objectAtIndex:ii]retain];
    }
    [donnee release];
    [wave release];


    Ton [wave release] final, tu l'as toujours ?
    Parce qu'il n'a rien à  faire ici


    plus de wave relase, plus de donne release
    [f doW];<br />NSMutableArray* donnee = [f tab];<br /><br />ObjectW* wave;<br />		<br />for(ii=0;loopLead&lt;nombreii;ii++){<br />			<br />wave = [donnee objectAtIndex:ii];<br />...<br />}<br />...<br />[f release];<br />
    


  • Philippe49Philippe49 Membre
    13:44 modifié #20
    dans 1217869166:

    le [tab release]; appel 12 fois le release de Wave et au 12ème crash !

    Je disais cela parce qu'il est un peu curieux que ce soit le dernier release qui crashe.
    Soit ton dernier wave a été traité différemment, soit le nombre d'éléments de tab n'est pas à  jour
  • ancrouancrou Membre
    13:44 modifié #21
    dans 1217869783:

    Je disais cela parce qu'il est un peu curieux que ce soit le dernier release qui crashe.
    Soit ton dernier wave a été traité différemment, soit le nombre d'éléments de tab n'est pas à  jour


    Finalement ça crash bien après mon code. Pourquoi, j'en sais rien.
    Bad access !

    Soit la fuite de mémoire soit le crash  ::)
  • Philippe49Philippe49 Membre
    13:44 modifié #22
    Bad Access c'est souvent essayer d'atteindre un pointeur désalloué

    Si ton code est pas trop long, envoies-le par courrier ou ici, je veux bien regarder.
  • Philippe49Philippe49 Membre
    13:44 modifié #23
    Voir peut-être ici
  • ancrouancrou Membre
    13:44 modifié #24
    dans 1217926401:

    Voir peut-être ici


    Je fais ni retain, ni release sur mon NSArrey, donc je ne fausse pas mon retaincount avec ce point
Connectez-vous ou Inscrivez-vous pour répondre.