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?
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?)
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.
Vous ne devez jamais utiliser retenueCount pour quoi que ce soit, avec ou sans ARC.
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.
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).
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
Non. Apple dit que vous n'en avez pas besoin car ARC s'en chargera pour vous.