[[object retain] autorelease] explication

cyranocyrano Membre
novembre 2010 modifié dans Objective-C, Swift, C, C++ #1
bonsoir,

je suis un tuto et j'ai

<br />- (NSDictionary *)propertyList<br />{<br />	NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:5];<br /><br />	..../....<br /><br />	return [[dictionary retain] autorelease];<br />}<br /><br />


je suis perplexe sur la derniere ligne.

1) vu son nom la methode doit renvoyer un object autorelease
2) creation en autorelease (ok)
..../...
3) pourquoi le retenir et l'autoreleaser de nouveau??

cette ligne est a supprimer ? ou ai je loupé un truc?

merci
«1

Réponses

  • 06:33 modifié #2
    J'ai jamais vraiment compris pourquoi certains faisaient ça. Soit il n'y a pas d'explication et c'est effectivement débile, soit j'ai râté quelque chose...
  • laudemalaudema Membre
    06:33 modifié #3
    Moi non plus je n'ai pas compris exactement pourquoi !
    Par contre j'en suis venu à  me méfier énormément de mes dictionnaires créés par des méthodes de convenance comme celle utilisée ici. J'ai eu tellement souvent de EXC_BAD_ACCESS où Instruments trouvait un dictionnaire responsable que j'ai pris l'habitude de les déclarer avec alloc]init] et placer mon autorelease plus loin dans le code.
    Le souci vient, m'a t'il semblé, de ce qu'ils sont placés dans l'autorelease pool de l'événement en cours (le process lancé par l'appui sur un bouton par exemple) qui est créé automatiquement par Cocoa au début de l'action et vidé à  la fin. Donc un "release" lui est envoyé et le tableau a un objet qui sera absent au prochain appel.
    C'est ce que j'avais cru en comprendre, je n'avais pas pensé à  faire retain]autorelease] ça aurait peut être fonctionné.
  • cyranocyrano Membre
    06:33 modifié #4
    ca veut dire:

    que a la création il est placer dans le pool autorelease de "l'action" (que je ne connaissais pas), et que le retain]autorelease] le place dans le pool "générale"?
  • CéroceCéroce Membre, Modérateur
    06:33 modifié #6
    dans 1289537792:

    Le souci vient, m'a t'il semblé, de ce qu'ils sont placés dans l'autorelease pool de l'événement en cours (le process lancé par l'appui sur un bouton par exemple) qui est créé automatiquement par Cocoa au début de l'action et vidé à  la fin. Donc un "release" lui est envoyé et le tableau a un objet qui sera absent au prochain appel.

    Le vocabulaire que tu utilises est maladroit...

    Le runtime ObjC possède une boucle d'événements. Au tout début de la boucle est créé un autorelease pool.
    Ensuite, le runtime récupère les événements (clics, frappe clavier, etc.) auprès de l'OS et les convertit en NSEvents,  puis les retransmet à  qui de droit (vue cliquée, premier répondeur, etc.).

    Ainsi, si on clique un bouton, le bouton envoie une message d'action à  sa cible; c'est dans la méthode d'action que notre code entre en scène.

    Enfin, quand tous les événements ont été traités, on arrive à  la fin de la boucle d'événements où l'autorelease pool est vidé:  tous les objets qui y ont été ajoutés par un message -[autorelease] recoivent un -[release].

    Ceci signifie que les objets autoreleasés n'existent que pendant l'itération actuelle de la boucle, ce qui suffit à  notre code pour créer des objets et les transmettre à  d'autres méthodes. Cela signifie aussi que:
    - si un objet doit être conservé plus d'une itération de la boucle, il faut le créer par +[alloc].
    - si on reçoit un objet autoreleasé et qu'on souhaite le conserver au-delà  d'une itération de la boucle, il faut lui envoyer un -[retain].
  • CéroceCéroce Membre, Modérateur
    06:33 modifié #7
    dans 1289545139:


    C'est intéressant, mais je ne suis pas convaincu par l'argumentation: si le getter me renvoie un objet, alors par convention (le nom de la méthode ne commence par alloc, new, copy ou create), je dois faire comme s'il était autoreleasé:
    - l'objet qui détient l'objet renvoyé ne peut de toute façon pas lui envoyer un -[release] tant que ma méthode s'exécute.
    - si elle veut conserver l'objet, la méthode actuelle doit de toute façon lui envoyer un -[retain]
  • cyranocyrano Membre
    06:33 modifié #8


    ouai, c'est fumeux.

    je préfère 10 fois le premier commentaire.

    quand au "pool de l'action" existe t'il?,  et les objets crées (autorelease) pendant le "déroulement de l'action" lui sont ils assignées?

    je n'ai jamais lu un truc pareil....
  • zoczoc Membre
    06:33 modifié #9
    dans 1289550054:

    quand au "pool de l'action" existe t'il?

    Non, il y a un seul pool à  chaque itération de la boucle de messages, sauf si, évidemment, le développeur en créée un explicitement.


    D'une manière générale, les pools sont gérés sur une pile, de sorte qu'autorelease place l'objet concerné dans le pool situé au somment de la pile.

  • mpergandmpergand Membre
    novembre 2010 modifié #10
    <br />NSString* oldName = [person name];<br />[person setName:@&quot;Alice&quot;];<br />NSLog(@&quot;%@ has changed their name to Alice&quot;, oldName);
    


    Pour moi, c'est clairement la faute du programmeur si ça plante.

    De même pour :
    Never just retain the string. This avoids the caller changing it under you without your knowledge. <br />Don&#39;t assume that because you&#39;re accepting an NSString that it&#39;s not actually an NSMutableString.<br /><br />- (void)setFoo:(NSString *)aFoo {<br />&nbsp; [foo_ autorelease];<br />&nbsp; foo_ = [aFoo copy];<br />}
    


    Perso, je ne fais jamais de copy.


    Par contre, je ne comprends pas ceci: (enfin si, c'est le même prob qu'au-dessus)
    When assigning a new object to a variable, <br />one must first release the old object to avoid a memory leak. <br />There are several &quot;correct&quot; ways to handle this. <br />We&#39;ve chosen the &quot;autorelease then retain&quot; approach because it&#39;s less prone to error. <br />Be aware in tight loops it can fill up the autorelease pool, and may be slightly less efficient, <br />but we feel the tradeoffs are acceptable.<br /><br />- (void)setFoo:(GMFoo *)aFoo {<br />&nbsp; [foo_ autorelease];&nbsp; // Won&#39;t dealloc if |foo_| == |aFoo|<br />&nbsp; foo_ = [aFoo retain];<br />}
    


    Et justement, pour les setters, j'utilise cette macro:
    #define COCOA_SET_VAR(old,new)	&#092;<br />			if(old!=new)			&#092;<br />				{				&#092;<br />				[old release];		&#092;<br />				old=[new retain];	&#092;<br />				}	<br /><br />plutôt que:<br /><br />#define COCOA_SETVAR(old,new)		&#092;<br />			[old autorelease];		&#092;<br />			[new retain];			&#092;<br />			old=new;					<br />
    


    Google Objective-C Style Guide
  • cyranocyrano Membre
    06:33 modifié #11

    Par contre, je ne comprends pas ceci: (enfin si, c'est le même prob qu'au-dessus)
    Code: [Sélectionner]
    When assigning a new object to a variable,
    one must first release the old object to avoid a memory leak.
    There are several "correct" ways to handle this.
    We've chosen the "autorelease then retain" approach because it's less prone to error.
    Be aware in tight loops it can fill up the autorelease pool, and may be slightly less efficient,
    but we feel the tradeoffs are acceptable.

    - (void)setFoo:(GMFoo *)aFoo {
      [foo_ autorelease];  // Won't dealloc if |foo_| == |aFoo|
      foo_ = [aFoo retain];
    }

    Et justement, pour les setters, j'utilise cette macro:
    Code: [Sélectionner]
    #define COCOA_SET_VAR(old,new) \
    if(old!=new) \
    { \
    [old release]; \
    old=[new retain]; \
    }

    plutôt que:

    #define COCOA_SETVAR(old,new) \
    [old autorelease]; \
    [new retain]; \
    old=new;




    inverser les deux lignes ne suffit pas?

    [new retain];
    [old release];
    old = new;
  • CéroceCéroce Membre, Modérateur
    06:33 modifié #12
    Ces trois exemples sont fumeux.

    Ex. 1: Comme tu le dis, c'est une faute grossière.

    Ex. 2: Si la propriété est déclarée en NSString, d'un point de vue conceptuel, il est de la responsabilité de l'objet qui la fournit qu'elle ne soit pas modifiée (c'est quand même à  ça que servent les objets-valeurs)

    Ex. 3: "It's less prone to error". ça c'est de l'argumentation  :D
    L'argument [tt]// Won't dealloc if |foo_| == |aFoo|[/tt] ne tient pas: si l'objet qui nous le transmet nous fournit aFoo, c'est qu'il ne l'a pas encore désalloué.

    Le code habituel est meilleur:
    <br />- (void)setFoo:(GMFoo *)aFoo {<br />&nbsp; [foo_ release]; <br />&nbsp; foo_ = [aFoo retain];<br />}<br />
    


    Si on s'est trompé dans les -[release] ça plantera dans cette méthode, pas plus tard quand l'autorelease pool sera vidé.



  • cyranocyrano Membre
    06:33 modifié #13
    <br />Le code habituel est meilleur:<br />Code: [Sélectionner]<br />- (void)setFoo:(GMFoo *)aFoo {<br />&nbsp; [foo_ release]; <br />&nbsp; foo_ = [aFoo retain];<br />}<br /><br />Si on s&#39;est trompé dans les -[release] ça plantera dans cette méthode, pas plus tard quand l&#39;autorelease pool sera vidé.<br /><br />
    


    ne tient pas compte du fait que aFoo et foo peuvent etre le meme objet (ATTENTION)
  • CéroceCéroce Membre, Modérateur
    06:33 modifié #14
    Non, il n'y a pas de problème: l'appelant ne nous transmet pas un objet qu'il a relâché. On n'écrit pas ça:
    <br />[monObjet release];<br />[machin setFoo:monObjet];<br />
    


    mais ça:
    <br />[machin setFoo:monObjet];<br />[monObjet release];<br />
    


    Si l'objet est le même, alors le release count est de 2 quand on appelle setFoo: (l'objet appelant retient l'objet, et l'objet appelé retient l'objet).
  • zoczoc Membre
    06:33 modifié #15
    dans 1289560748:

    ne tient pas compte du fait que aFoo et foo peuvent etre le meme objet (ATTENTION)

    En fait, ça dépend de comment sont écris les getters...


    Dans l'exemple du setter de Ceroce, si le getter est:


    <br />- (GMFoo *)foo<br />{<br />&nbsp; &nbsp;  return foo_;<br />}<br />
    



    alors "[obj setFoo:[obj foo]]" va surement faire planter le code de céroce (m'enfin bon a priori, écrire cela n'a absolument aucun intérêt). Maintenant, si le getter fait un "retain autorelease", le code du setter de céroce est correct.
  • CéroceCéroce Membre, Modérateur
    novembre 2010 modifié #16
    Mon code planterait si on écrivait [tt][self setFoo:[self foo]][/tt].

    EDIT: (Pardon, j'ai mal lu ta réponse zoc, effectivement, tu as généralisé).
  • mpergandmpergand Membre
    06:33 modifié #17
    dans 1289561770:

    alors "[obj setFoo:[obj foo]]" va surement faire planter le code de céroce (m'enfin bon a priori, écrire cela n'a absolument aucun intérêt).


    C'est ça le problème, tant que l'on code pour soit uniquement, on sait ce que l'on fait, mais dès que l'on distribue le code, alors il faut se mettre en mode "paranoà¯aque", car on ne peut pas savoir comment les autres programment.
  • cyranocyrano Membre
    06:33 modifié #18
    je resume :

    retain] autorelease] == exotique!

    la bonne façon du setter en mode retain

    [new retain];
    [old release];
    old = new;

    a+

  • AliGatorAliGator Membre, Modérateur
    novembre 2010 modifié #19
    Non non non cyrano, il y a un gros intérêt à  faire retain+autorelease quand même !

    En effet, ça permet si jamais l'objet A, qui contient l'objet B qu'on récupère du getter, est releasé entre temps, de ne pas tout foutre en l'air.

    Exemple :
    @interface Person : NSObject {<br />&nbsp; NSString* _firstName;<br />&nbsp; NSString* _lastName;<br />}<br />-(void)initWithData:(NSData*)data; // un constructeur à  partir de NSData, imaginons<br />@property(nonatomic, retain) NSString* firstName;<br />@property(nonatomic, retain) NSString* lastName;<br />@end
    
    Si le getter de "firstName" par exemple est juste implémenté comme cela :
    -(NSString*)firstName { return _firstName; }
    
    Alors si on a un code comme le suivant, qui pourtant parait tout à  fait correct et n'est pas spécialement une faute, ça va crasher :
    Person* p = [[Person alloc] initWithData:someData];<br />NSString* fn = [p firstName];<br />[p release];<br />NSLog(@&quot;first name: %@&quot;,firstName); // crash
    
    En effet, comme l'objet Person a reçu un release entre temps, il a été détruit, son dealloc a été appelé, la chaà®ne firstName a été released et détruite entre temps... et au final l'objet qui avait été retourné par [tt][p firstName][/tt], et qui était valide à  ce moment là , ne l'est plus après le [tt][p release][/tt] ! Pourtant quand on lit le code qui utilise l'objet Person, ça ne saute pas aux yeux (et en plus comme on n'est pas sensé connaà®tre l'implémentation de la classe Person (abstraction boite noire) on n'a pas à  aller regarder dans le code de Person.m pour réfléchir à  si on doit faire un retain de fn ou pas...)

    Alors que si le getter de "firstName" est écrit avec [tt]return [[_firstName retain] autorelease];[/tt] là  il n'y a plus de risque. C'est d'ailleurs comme ça, si je ne dis pas de bétises, que les @property synthétisées automatiquement par @synthesize sont écrites.


    En conclusion :
    - Soit vous utilisez des @property et des @synthesize et les setters et getters vont être écrits automatiquement avec la bonne forme et vous ne risquez pas d'avoir d'ennuis
    - Soit si vous écrivez vos setters et getters vous-même pensez :
      - soit à  envoyer un "autorelease" à  l'ancienne valeur dans le setter, au lieu d'un simple release
      - mais de toute façon à  faire retain+autorelease dans le getter pour pas tomber sur le bug du container qui est releasé et release son contenu implicitement !
  • cyranocyrano Membre
    06:33 modifié #20
    merci

    c'est plus clair
  • AliGatorAliGator Membre, Modérateur
    novembre 2010 modifié #21
    Notez qu'il y a un autre exemple type que celui du "conteneur releasé", qui est tout simplement le cas de l'appel au setter de la variable :
    NSString* fn = [p firstName];<br />[p setFirstName:@&quot;Nouveau nom&quot;]; // a pour effet de faire un release sur l&#39;ancienne NSString ...<br />NSLog(@&quot;%@ was changed to %@&quot;,oldName,[p firstName]); // du coup crash
    
    Du moins ce code là  crash si firstName est implémenté par un simple return de la variable d'instance (et pas retain+autorelease) et si le setter fait un release de la valeur précédente (et pas un autorelease, ce qui pourrait sauver la mise dans ce cas spécifique mais ne solutionnerait pas le problème de l'exemple précédent)
  • laudemalaudema Membre
    06:33 modifié #22
    dans 1289546206:

    Le vocabulaire que tu utilises est maladroit...

    Oui, je sais, toutes mes excuses, je manque de l'usinage scolaire... La doc parle mieux que moi:
    http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/IB_UserGuide/Layout/Layout.html#//apple_ref/doc/uid/TP40005344-CH19-SW23

    The Application Kit automatically creates a pool at the beginning of an event cycle (or event-loop iteration), such as a mouse down event, and releases it at the end, so your code normally does not have to worry about them.
    ...

    Et c'est comme ça qu'une fenêtre qu'on bouge peut planter l'application: à  la sortie, quand on l'affiche, l'objet est là , puis quand il faut redessiner il n'est plus là .. Peut être qu'un retain]autorelease] aurait arrangé les choses, j'essayerais la prochaine fois, si j'y pense...
    D'un autre côté, justement, créer des objets avec alloc+init (et les relâcher soi même) est plus clair, plus "carré". Et souvent les objets Cocoa offrent plus de possibilité de création à  partir d'autres objets dans les méthodes d'instance que via les méthodes de classe.
    Finalement, pour débuter je recommanderais plutôt les alloc]initWith...:] release (+ loin)/autorelease], et là  on ne sent pas le besoin de rajouter un retain ;-) Mais pour revenir à  la question de départ je présume que l'auteur du livre aurait pu prendre ma signature ...
  • CéroceCéroce Membre, Modérateur
    06:33 modifié #23
    dans 1289593563:

    Et c'est comme ça qu'une fenêtre qu'on bouge peut planter l'application: à  la sortie, quand on l'affiche, l'objet est là , puis quand il faut redessiner il n'est plus là .. Peut être qu'un retain]autorelease] aurait arrangé les choses, j'essayerais la prochaine fois, si j'y pense...

    S'il faut redessiner, c'est que tu es dans une itération suivante de la boucle, alors ça plante si l'objet n'a pas été retenu.
  • cyranocyrano Membre
    06:33 modifié #24
    dans 1289575597:

    Non non non cyrano, il y a un gros intérêt à  faire retain+autorelease quand même !

    En effet, ça permet si jamais l'objet A, qui contient l'objet B qu'on récupère du getter, est releasé entre temps, de ne pas tout foutre en l'air.



    ok, j'ai bien compris le coup du "container releasé" qui "release sa property" dans la meme boucle d'événement.

    mais dans le cas du code :

    <br />- (NSDictionary *)propertyList<br />{<br />	NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithCapacity:2];<br />	[dictionary setObject:[[self representedObject] contents] forKey:BCInfosKey];<br />	<br />	if (! [self isLeaf]) {<br />		/* <br />		 idem avec les enfants (recursif)<br />		 */<br />		NSMutableArray * childrenAsPlist;<br />		childrenAsPlist = [NSMutableArray arrayWithCapacity:[[self childNodes] count]];<br />		for(BC_BrowserTreeNode *node in [self childNodes]) {<br />			[childrenAsPlist addObject:[node propertyList]];<br />		}<br />		[dictionary setObject:childrenAsPlist forKey:BCChildrenKey];<br />	}<br />	<br />	return [[dictionary retain] autorelease];<br />}<br /><br />
    


    dictionary n'est pas une property, et donc retain] autorelease] ne sert a rien?
  • zoczoc Membre
    06:33 modifié #25
    dans 1289815884:

    dictionary n'est pas une property, et donc retain] autorelease] ne sert a rien?

    Effectivement. la méthode "dictionnaryWithCapacity" de NSMutableDirectory retourne (toujours comme son nom l'indique) un objet déjà  autoreleasé.

  • mpergandmpergand Membre
    novembre 2010 modifié #26
    J'évite d'utiliser les machins du genre [retain] autorelease] et autres, ça peut donner de mauvaises habitudes, car ça ne marche pas en coreFondation qui ne possède pas d'autorelease !

    Exemple d'une classe C++ avec une variable d'instance de type CFStringRef:

    <br />class MyClass<br />{<br />			CFStringRef	fName;	// variable type fondation (nécessite un release)<br />			<br />		public:		<br />			<br />			// constructeue<br />			MyClass(CFStringRef name) : fName(NULL) <br />				{ <br />				if(name)<br />					fName=(CFStringRef)CFRetain(name); <br />				}<br />			// destructeur<br />			virtual ~MyClass()<br />				{<br />				if(fName)<br />					CFRelease(fName);<br />				}<br /><br />			MyClass(const MyClass&amp; device)			// contructeur de copie<br />				{<br />				*this=device;<br />				}<br />					<br />			MyClass&amp; operator=(const MyClass&amp; device)	// opérateur d&#39;affectation<br />				{<br />				fName=NULL;<br />				if(device.fName)<br />					fName=(CFStringRef)CFRetain(device.fName);<br />					<br />				return *this;<br />				}<br />			<br />			CFStringRef name() { return fName; }<br />			<br />			void setName(CFStringRef name) <br />				{ <br />				if(fName)<br />					CFRelease(fName); <br />					<br />				fName=NULL;<br />				<br />				if(name)<br />					fName=(CFStringRef)CFRetain(name);<br />				}<br /><br />};<br /><br />
    


    Si je fais:
    <br />	CFStringRef strConst=CFSTR(&quot;Alfred&quot;);			// c&#39;est un objet constant<br />	CFStringRef name=CFStringCreateMutableCopy (NULL,0,strConst);	// donc crée une copie<br />	CFShow(name);<br />	<br />	MyClass c(name);<br />	CFRelease(name);<br />	<br />	name=c.name();<br />	c.setName(CFSTR(&quot;!!&quot;));<br />	CFShow(name);<br />	CFShow(c.name());<br /><br />
    


    Ca ne plante pas, mais ça m'affiche:

    Alfred
    \u2030,\u2020\
    !!

    Mais name est bien releasé !

    Donc, il faut bien faire un retain sur name avant le setName()

    En C++, on a l'habitude de faire des copies d'objets, à  la condition d'implémenter le constructeur de copie
    et l'opérateur d'affectation,
    donc on peut faire:
    MyClass c1(c);

    et là  plus de problème: CFShow(c1.name(); affiche bien "Alfred"


    Et par ailleurs, on voit que le C++ c'est quand même bien relou !
  • AliGatorAliGator Membre, Modérateur
    06:33 modifié #27
    C'est pas faux, mais en mm temps c'est pas tous les jours qu'on fait du CoreFoundation sans faire de Cocoa (sans pouvoir faire utiliser la couche NSObject pour profiter des NSAutoreleasePool, comme là  tu aurais pu le faire en castant par toll-free-bridging le CFStringRef en NSString* pour lui envoyer un autorelease).

    Certes il y a des cas bien spécifiques où tu peux être amener à  ne faire que du CoreFoundation sans Cocoa (ou avec mais sans toll-free-bridging ou autre mécanisme permettant d'accéder au mécanisme d'autorelease), mais dans ce cas ce ne sont de toute façon plus les mêmes règles qui sont utilisées pour la gestion mémoire (on tourne plutôt autour de la Create Rule & co, du coup les fonctions qui créent des objets ne sont plus forcément celles qui les détruisent puisqu'il n'y a justement pas de notion d'autorelease) donc c'est une autre façon de voir les choses.

    Dans le cas le plus courant utilisé ici, où l'on utilise Cocoa et très peu CoreFoundation directement, encore moins mixé avec du C++, utiliser retain+autorelease pour les raisons évoquées plus haut me semble être approprié. Après je dis pas que dans les cas d'environnement moins courants tels que celui que tu présentes c'est pas gênant mais ça reste moins courant et de toute façon régi à  une Memory Policy différente.
  • mpergandmpergand Membre
    06:33 modifié #28
    Et que penses-tu de ça:

    <br />// même chose qu&#39;au-dessus, mais avec un buffer de char comme variable !<br /><br />	char* buffer=malloc(10);<br />	<br />	MyClass c(buffer);<br />	free(buffer);<br /><br />	buffer=c.buffer();<br />	c.setBuffer(malloc(10));<br />	<br />	printf(&quot;buffer %x&#092;n&quot;,buffer); // ???!!!!<br /><br />
    



  • AliGatorAliGator Membre, Modérateur
    06:33 modifié #29
    Je pense que ce n'est pas du Cocoa :P
    Un mélange de C++ et de C, mais aucune trace de Cocoa là  dedans, donc c'est hors du débat sur les mécanismes de gestion mémoire Cocoa avec leur retain, release, alloc, init, etc :P

    Et c'est bien pour ça que ce mécanisme de reference counting et d'autorelease de Cocoa est bien pratique, c'est parce que sans lui donc dans des contextes pur C ou C++ et pas Obj-C avec NSObject et ses mécanismes, est bien pratique, parce que dans des contextes où il n'est pas disponible (comme CoreFoundation utilisé avec du C pur ou avec du C++) on voit bien que c'est vite le boxon (qui a déjà  codé en C et C++, sans mécanismes de ReferenceCounting avec AutoreleasePool, sait à  quel point c'est vite casse-tête, encore plus dans des environnements multithreadés)

    Si MyClass est la mm classe qu'au dessus, au mieux le lien avec le reste du forum c'est que tu utilises CoreFoundation, avec CFRetain et CFRelease, et donc que c'est la CreateRule qui est de mise, mais en aucun cas les règles de gestion mémoire de Cocoa ;)

  • mpergandmpergand Membre
    06:33 modifié #30
    dans 1289833865:

    Et c'est bien pour ça que ce mécanisme de reference counting et d'autorelease de Cocoa est bien pratique,


    Et encore, il faut que le programmeur de la classe est bien prévu le truc ...

    En java ou C# pas de problème, pareil pour ObjC + garbage collector.

    En C++, ça marche pas.
    En Cocoa, ça peut foirer !

    Pas bon ...
  • cyranocyrano Membre
    06:33 modifié #31
    dans 1289831465:

    Et que penses-tu de ça:

    <br />// même chose qu&#39;au-dessus, mais avec un buffer de char comme variable !<br /><br />	char* buffer=malloc(10);<br />	<br />	MyClass c(buffer);<br />	free(buffer);<br /><br />	buffer=c.buffer();<br />	c.setBuffer(malloc(10));<br />	<br />	printf(&quot;buffer %x&#092;n&quot;,buffer); // ???!!!!<br /><br />
    



    c++ et malloc beurk

    sans connaitre le contructeur MyClass(char * buffer), et les methodes buffer() et setBuffer(Char * buffer)

    pas grand chose  :D
Connectez-vous ou Inscrivez-vous pour répondre.