Désolé pour une description longue, mais les questions ne sont pas si faciles ...Suivre tous les alloc/allocWithZone/dealloc
Mon projet écrit sans GC. Récemment j'ai trouvé une fuite de mémoire que je ne peux pas trouver. J'ai utilisé Xcode Analyzer sans résultat. J'ai lu mon code ligne par ligne et vérifié tous les alloc/release/copy/autorelease/mutableCopy/retain et pools ... - toujours rien. Préambule: Standard Instruments et Omni Leak Checker ne fonctionnent pas pour moi pour une raison quelconque (Omin Tool rejette mon application, Instruments.app (Leaks) mange trop de mémoire et de CPU, donc je n'ai aucune chance de l'utiliser).
Donc, je veux écrire et utiliser mon propre code pour accrocher & suivre toutes les statistiques alloc/allocWithZone:/dealloc messages pour écrire une bibliothèque de vérification des fuites (l'objectif principal est seulement de marquer les noms des classes d'objets avec possible fuites).
La principale technique d'accrochage que j'utilise:
Method originalAllocWithZone = class_getClassMethod([NSObject class],@selector(allocWithZone:));
if (originalAllocWithZone)
{
imp_azo = (t_impAZOriginal)method_getImplementation(originalAllocWithZone);
if (imp_azo)
{
Method hookedAllocWithZone = class_getClassMethod([NSObject class],@selector(hookedAllocWithZone:));
if (hookedAllocWithZone)
{
method_setImplementation(originalAllocWithZone,method_getImplementation(hookedAllocWithZone));
fprintf(stderr,"Leaks Hook: allocWithZone: ; Installed\n");
}
}
}
-
Code
- comme cela pour crochet de la méthode alloc, et dealloc comme méthode de NSObject catégorie.
Je sauverai IMP pour la mise en œuvre des méthodes précédentes registre & puis calculera tous alloc/allocWithZone: appels comme incrément (+1) stat-tableau des valeurs NSInteger et les appels dealloc comme décrémentation (-1).
En tant que point final, j'appelle l'implémentation précédente et la valeur de retour.
En principe tout fonctionne très bien. En cas de besoin, je peux même détecter quand les classes font partie du cluster de classe (comme NSString, NSPathStore2, NSDate, __NSCFDate) ... via une fonction normalize (mais cela n'a pas d'importance pour les problèmes décrits ci-dessous) .
Cependant cette technique a quelques problèmes:
- Toutes les classes peuvent être pris, par exemple , [date NSDate] ne se coince pas dans alloc/allocWithZone: du tout, cependant, je peux voir Comme j'essaie d'utiliser la technique de détection automatique de singleton (basée sur readContent readind) pour exclure automatiquement certains objets des statistiques finales, la création de NSLocale se bloque à l'étape pré-init lors du démarrage de l'application Cocoa complète (en fait, même simple utilitaire de ligne de commande Objective-C avec le framework Foundation inclus a une initialisation supplémentaire avant main()) - par GDB il y a allocWithZone: appelle l'un après l'autre, ....
projet Sources complètes Concept-projet téléchargé ici: http://unclemif.com/external/DILeak.zip (3,5 Kb)
Run make de Terminal.app pour le compiler, exécutez ./concept pour le montrer en action.
La 1ère question : Pourquoi je ne peux pas attraper toutes les allocations d'objet en accrochant alloc & allocWithZone: méthodes?
Le 2ème question: Pourquoi accroché allocWithZone: gèle à CFGetRetainCount (ou [inst retainCount]) pour certaines classes ...
Wow. Cela va vraiment loin pour éviter d'utiliser les solutions évidentes, car elles sont trop lentes ou utilisent trop de mémoire, et pourtant, on se demande si un tel argument est valable même quand l'outillage (quel que soit le type que vous utilisez) ne doit pas être laissé dans la construction finale, mais seulement pour être utilisé lorsqu'un problème est suspecté. Je pense que pour 99,999% des gens, utiliser les outils standards est la bonne réponse, et rouler le vôtre est une solution bizarro que peu d'autres développeurs trouveront utile. –