Tester la libération mémoire d'un objet
ghusse
Membre
Bonjour,
Je suis débutant en cocoa, j'essaye de créer quelques classes et objets histoire de me faire la main. J'expérimente également les outils permettant les tests unitaires du même coup.
Mon problème, c'est que j'aimerai vérifier dans mes tests unitaires que mes objets sont libérés correctement lorsque j'envoie le message "release". La première idée c'est de vérifier que la valeur des pointeurs est bien à nil mais ça ne fonctionne pas. Les pointeurs pointent vers des cases mémoires libérées...
J'aimerai vraiment bien vérifier pendant mes tests que mes libérations se font correctement, sans avoir à passer ma vie sur Instruments.
Est-ce que quelqu'un peu m'aider ?
Merci
Je suis débutant en cocoa, j'essaye de créer quelques classes et objets histoire de me faire la main. J'expérimente également les outils permettant les tests unitaires du même coup.
Mon problème, c'est que j'aimerai vérifier dans mes tests unitaires que mes objets sont libérés correctement lorsque j'envoie le message "release". La première idée c'est de vérifier que la valeur des pointeurs est bien à nil mais ça ne fonctionne pas. Les pointeurs pointent vers des cases mémoires libérées...
J'aimerai vraiment bien vérifier pendant mes tests que mes libérations se font correctement, sans avoir à passer ma vie sur Instruments.
Est-ce que quelqu'un peu m'aider ?
Merci
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Mettre avant @implementation la déclaration d'un compteur d'instances
static int numberOfInstances=0;
@implementation MyClass
...
Dans toutes les méthodes d'initialisation, mettre
numberOfInstances++;
NSLog(@Allocation. nombre d'instances: %d, numberOfInstances);
en prenant garde à ce qu'une même initialisation ne provoque qu'un seul ++
Dans dealloc, mettre
numberOfInstances--;
NSLog(@Deallocation. Nombre d'instances: %d, numberOfInstances);
- (oneway void)release
{
NSLog(@coucou);
[super release];
}
Voir http://www.oreillynet.com/pub/a/mac/2003/06/10/memory_mgmt.html
Le crocodile (et bien d'autres) attend le pot d'arrivée!
Je vais essayer de répondre dans l'ordre :
Par contre, je crois que ça devrait pouvoir se faire en utilisant STAssertThrows(). C'est une assertion permettant de tester qu'un accès lève une exception.
Donc en essayant d'accéder à une propriété de l'objet tel que retainCount, on peut tester si une exception est levée (comme BAD ACCESS) non ?
Cela signifie que j'ai besoin de quelque chose, dans du code, qui une fois appelé me dit OK ou KO...
Je sais que performance tool permet de traquer les fuites mémoires. C'est un outil pour avoir un aperçu global et détecter les fuites une fois l'appli bouclée. Moi, j'ai besoin d'un test unitaire et les outils Apple Instruments ne correspondent pas à mes besoins.
J'aurais juste besoin de tester si un objet est bien désalloué correctement. Ma connaissance du cocoa est trop évasive pour savoir comment c'est faisable.
Sinon, j'ai testé l'utilisation de STAssertThrows([objet retainCount],@Normalement libéré). ça ne fonctionne pas : en fait ce n'est pas une exception qui est levée, c'est carrément le programme qui plante en essayant d'accéder à une adresse mémoire libérée.
ben voir plus haut.
Ca fait 4-5 lignes de codes, éventuellement à placer entre des #ifdef DEBUG #endif si on veut les supprimer rapidement.
Il n'y a pas de méthode miracle pour tester une bonne gestion de la mémoire. C'est du ObjectAlloc, du MallocDebug...
Le plus compliqué en général, c'est pas de gérer la mémoire de ses propres objets ; ça c'est peanuts.
D'autant plus que la synchronisation du release n'est pas assurée.
Le retainCount est souvent (momentanément) supérieur à ce que l'on attend.
Essai : % gcc pgm.m -o pgm -framework Foundation
Affichage : 1 1
l'exécution du [str release] a une priorité plus faible que celle de la suite.
Je suis assez monomaniaque des tests unitaires, voire XP. Ce qui signifie en théorie que du code n'est écrit que parce qu'un test échoue. Si je ne peux pas tester le fait que mes données sont correctement libérées ...
Effectivement, peut-être que l'incrémentation/décrémentation d'un compteur entre #if DEBUG #endif suffirait, pour mes propres objets.
Maintenant, mes objets contiennent des propriétés NSString*, comment tester que les ressources sont bien libérées aussi sur ces objets ?
Résultat :
% pgm
2008-03-11 17:38:50.904 pgm[992:10b] 1
pgm(992) malloc: *** error for object 0x105450: double free
*** set a breakpoint in malloc_error_break to debug
2008-03-11 17:38:50.907 pgm[992:10b] finally
%
Merci beaucoup !
Et ça ne fonctionne pas. Le script de test (car les tests sont lancés après la compilation de manière automatique par un script) renvoie un FAIL.
Il s'arrête sur cette ligne :
- (void)dealloc
{
NSLog(@dealloc de %@",self);
...
...
[super dealloc];
}