Gestion mémoire et Autorelease
belt
Membre
Après lecture de différents articles consacrés à la gestion de la mémoire sous cocoa, il semble que les objets alloués par des appels aux méthodes de classe (celles commençant par un "+") et dont le nom débute par le nom de la classe (moins le NS et avec la permière lettre en minuscule), sont automatiquement placées dans le autorelease pool.
( ex : méthode arrayWithObjects de NSArray).
Il me semble qu'il y en a beaucoup d'autres. Est-ce juste ?
D'après les différentes documentations, la libération de l'objet s'effectue "un peu après" l'appel à la méthode. Cela me paraà®t un peu vague. Quelqu'un a-t-il des quelques précisions sur ce sujet. Et d'ailleurs, par quel mécanisme s'effectue cette libération ? ( Y-a-t-il un Thread qui s'occupe de ça ? )
( ex : méthode arrayWithObjects de NSArray).
Il me semble qu'il y en a beaucoup d'autres. Est-ce juste ?
D'après les différentes documentations, la libération de l'objet s'effectue "un peu après" l'appel à la méthode. Cela me paraà®t un peu vague. Quelqu'un a-t-il des quelques précisions sur ce sujet. Et d'ailleurs, par quel mécanisme s'effectue cette libération ? ( Y-a-t-il un Thread qui s'occupe de ça ? )
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
En fait, il n'y a que très peu de méthodes "+" (méthodes de classe) qui ne placent pas l'objet créé dans l'autoreleasepool. La plus connue est alloc, mais il y a aussi sharedInstance par exemple.
Lorsque l'autoreleasepool est détruit, chaque objet qu'il contient reçoit alors un message release (ce qui peut mener à la destruction de l'objet).
Dans une appli cocoa basée sur l'ApplicationKit, pour simplifier, un autoreleasepool est créé au début de chaque boucle d'événement (grosso modo, lorsque l'application reçoit un événement), puis il est détruit à la fin de cette boucle (quand l'événement a été traité). La durée de vie est donc très courte.
EDIT : merci à Renaud pour sa vigilence.
.
Toutefois, cette durée de vie est dans la plupart des cas suffisante (jusqu'à la fin de l'exécution de la méthode, et de toutes celles appelées directement...)
C'est justement à propos de la libération de la mémoire. Dans mon code j'ai eu besoin de:
Du coup je me dit: "Hey pti gars, oublie pas de libéré les objets créés à la fin!"
Ni une ni deux je fait:
Et là bam! Bad Access Error!
Du coup j'ai l'impression qu'il se sont libéré tout seul les coco! Ca corresponderais à ce que vous disiez plus haut? Me trompe-je?
Tu n'as mis nulle part un [touch retain] ou un [touch copy] ou encore un touch = [[UITouch alloc] init], donc tu n'as aucune raison d'écrire un [touch release].
Et en fait c'est pareil pour ta selectedCase.
- Soit caseAtPoint renvoie une GWCase qui est une variable d'instance de ton "self", qui n'a pas de raison d'être supprimée tant que self existe, et comme tu n'as fait nulle part de retain sur cette GWCase y'a pas de raison que tu fasses de release correspondant ici (si c'est une variable de classe tu as sans doute fait un alloc/init à l'initialisation de ta classe, et y'a bien un release correspondant à faire mais il est dans le dealloc donc ; dans ta méthode touchBegan où tu as mis le code cité tu n'as pas fait de alloc/retain/copy donc pas de release par contre)
- Soit caseAtPoint renvoie un nouvel objet GWCase, mais qui si tu as bien fait les choses doit être en autorelease, c'est à dire que das le code de caseAtPoint tu as un alloc/init qqpart qui crée ton objet GWCase si c'est le cas, mais tu dois alors aussi avoir un autorelease.
En effet la règle est on ne peut plus simple : c'est celui qui fait le alloc, retain ou copy qui doit faire le release correspondant. Si c'est une variable de classe, alloc/init dans l'initialisation de ta classe et release correspondant dans le dealloc. Si c'est une variable locale de ton code, alloc/init au début du code quand tu crées ta variable donc, ben release dans ce même bloc de code quand tu n'as plus besoin de la variable. (Ou autorelease au lieu de release si tu dois renvoyer cette variable, pour dire "bon c'est à moi de penser au release mais faut pas le faire tout de suite parce que le code qui m'a appelé veut que je lui retourne cette variable... mais tu penseras à faire tout seul le release plus tard").
---
C'est plutôt bien résumé à cet endroit dans la doc, quand on y pense la règle est simple, si tu alloc/new/retain tu release/autorelease, sinon c'est pas à toi de gérer, point barre
Tu as aussi des exemples pratiques, avec explications, de cas où il faut faire le release et ceux où il faut pas, c'est dans la même section de la doc, quelques chapitres plus haut, ici