web-dev-qa-db-fra.com

Comment vérifier le nombre de références en mode ARC?

J'ai utilisé pour vérifier que certaines de mes variables avaient le nombre de retenues attendu en utilisant [myVar retenueCount] sous le débogueur, en particulier pour var qui n'avait pas de désallocation personnalisée.

Comment faites-vous cela en mode ARC? Comment vous assurez-vous qu'il n'y a pas de fuites de mémoire?

Remarque: Je comprends qu'ARC devrait gérer cela pour moi, mais la vie est loin d'être parfaite, et dans la vraie vie, vous avez des objets qui sont parfois alloués par des bibliothèques tierces (en utilisant retenue?) Et jamais désalloués.

Image que je fais ceci:

MyObj *myObj=[[MyObj alloc] init];

alors j'appelle

[somethingElse doSomethingWithMyObj:myObj];

et plus tard, je fais

myObj=NULL;

Si mon programme fonctionne bien, je m'attends à ce que myObj soit détruit, mais cela ne semble pas être le cas ...

Alors, comment puis-je suivre cela, surtout si quelque chose d'Else n'est pas géré par moi?

Maintenant, à propos des outils: il semble extrêmement difficile d'exécuter des outils de mémoire sur mon mac (avec 5 Meg) sans redémarrer le mac et recommencer à zéro. C'est vraiment ennuyeux! Les instruments continuent de planter avant même que le programme ne démarre, alors existe-t-il une solution alternative?

34
tomsoft

Vous pouvez utiliser CFGetRetainCount avec des objets Objective-C, même sous ARC:

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));

Ceci n'est pas particulièrement utile pour le débogage, cependant, pour des raisons amplement décrites ailleurs . Si vous avez besoin de comprendre où un objet est conservé et libéré, consultez cette réponse pour obtenir de l'aide sur l'utilisation de l'instrument Allocations.

Le seul cas que j'ai trouvé où l'examen du nombre de retenues est réellement utile est dans une méthode dealloc, lorsque quelque chose conserve et libère automatiquement l'objet désalloué. Cela entraînera un crash plus tard lorsque le pool de libération automatique est vidé. Vous pouvez identifier la cause de cela en vérifiant le nombre de retenues avant et après chaque message. De cette façon, j'ai découvert que la méthode observationInfo (qui n'est elle-même généralement utile que pour le débogage) conserve et libère automatiquement self. Cependant, même ce type de problème peut généralement être résolu sans examiner le nombre de retenues, simplement en enveloppant le corps entier de dealloc dans un @autoreleasepool bloquer.

Cependant, le nombre de retenues peut être utilisé pour en savoir plus sur l'implémentation de certaines classes. (Ne faites cela que pour le divertissement ou la curiosité! Ne vous fiez jamais aux détails d'implémentation non documentés dans le code de production!)

Par exemple, essayez ceci immédiatement à l'intérieur du @autoreleasepool dans main:

NSNumber *n0 = [[NSNumber alloc] initWithInt:0];
NSLog(@"0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef)n0));
// Prints 2 in my test

Donc NSNumber met probablement en cache (ou du moins réutilise) certaines instances. Mais pas les autres:

n0 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n0));
// Prints 1 - I am the sole owner of this instance.  There could be weak
// or unretained references to it, but no other strong references.

NSNumber *n1 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints 1 again.  New instance with same value as prior instance.
// You could of course compare pointers to see that they are separate
// instances.

Vous pouvez même découvrir que NSNumber renvoie un singleton si vous alloc mais n'initialisez pas:

n1 = [NSNumber alloc];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints -1.

(Notez que vous pouvez également en savoir plus sur NSNumber en consultant le code source de Core Foundation, qui est disponible sur http://opensource.Apple.com . Mais qui sait quoi vous trouverez peut-être si vous regardez le nombre de conserver des objets qui ne sont pas sans pont avec des objets dans Core Foundation?)

99
rob mayoff

Non. ARC gère la gestion de la mémoire pour vous et ne vous permet pas d'appeler retenueCompte et même si vous pouviez le voir, le numéro qu'il renvoie n'a pas de sens pour vous. Si vous le souhaitez, vous devez effectuer le profilage de la mémoire dans les instruments avec les instruments Leaks and Allocations. C'est la meilleure façon de regarder et de voir comment votre application alloue de la mémoire et de détecter toute utilisation incorrecte de la mémoire.

41
Colin Wheeler

Vous ne devez jamais utiliser retenueCount pour quoi que ce soit, avec ou sans ARC.

Quand utiliser -retainCount?

31
UIAdam

Utilisez Instruments et localisez l'objet que vous souhaitez suivre en recherchant le nom de classe ou l'adresse du pointeur si vous l'avez dans la "Liste des objets".

Lorsque vous l'avez localisé, appuyez sur la flèche de divulgation sur l'instance. Cela vous amène à une vue historique pour les fichiers conservés et relâchés.

Si vous développez la vue de détail du côté droit, vous verrez également la pile d'appels pour chaque conservation/libération.

Instruments showing object history and callstack detail

15
Henrik Hartz

Je crois que la seule façon est de profiler votre application en utilisant l'instrument d'allocations. Vous devrez cliquer sur le descripteur d'informations (le "i" à côté de Allocation dans le volet gauche) et cliquer sur "Record Reference Counts". Vous pouvez ensuite profiler votre application et rechercher la classe spécifique que vous souhaitez inspecter. De là, vous pouvez trouver le nombre de retenues dans le volet Détail étendu pour chaque instance de la classe.

Vous pouvez également le faire en utilisant Leaks (car je pense que c'est une variante de l'instrument Allocations).

3
Aaron Hayman

Obtenez le retainCount de l'objet?

Vous pouvez simplement créer un point d'arrêt et saisir la commande ci-dessous pour obtenir le retainCount de l'objet

po object.retainCount
2
Jason Yu

Non. Apple dit que vous n'en avez pas besoin car ARC s'en chargera pour vous.

0
Darren