web-dev-qa-db-fra.com

Comment déboguer les fuites de mémoire lorsque l'instrument Leaks ne les affiche pas?

J'ai une application iOS écrite en Swift qui fuit de la mémoire - dans certaines situations, certains objets devraient être libérés mais ils ne le sont pas. J'ai appris le problème en ajoutant simplement deinit déboguer des messages comme celui-ci:

deinit {
    println("DEINIT: KeysProvider released")
}

Ainsi, le message deinit devrait être présent dans la console après de tels événements qui devraient provoquer la libération de l'objet. Cependant, pour certains des objets qui doivent être libérés, le message est manquant. Pourtant, Leaks Developer Tool ne montre aucune fuite. Comment résoudre une telle situation?

53
Rasto

Dans Xcode 8, vous pouvez cliquer sur le bouton "Debug Memory Graph", debugmemorygraphbutton dans la barre d'outils de débogage (affichée en bas de l'écran):

debug memory graph

Identifiez simplement l'objet dans le panneau de gauche qui, selon vous, aurait dû être désalloué, et il vous montrera le graphique de l'objet (montré dans le canevas principal, ci-dessus). Ceci est très utile pour identifier rapidement où les références fortes ont été établies sur l'objet en question. À partir d'ici, vous pouvez commencer votre recherche, en diagnostiquant pourquoi ces références fortes n'ont pas été résolues (par exemple, si l'objet en question a une référence forte à partir d'autre chose qui aurait dû être désalloué, regardez également le graphique de cet objet, et vous pouvez trouver le problème (par exemple, cycles de référence forts, temporisations répétitives, etc.).

Remarquez que dans le panneau de droite, je vois l'arborescence des appels. J'ai obtenu cela en activant l'option de journalisation "pile malloc" dans les paramètres du schéma:

malloc stack

Quoi qu'il en soit, après avoir fait cela, on peut ensuite cliquer sur la flèche à côté de l'appel de méthode approprié affiché dans la trace de pile dans le panneau de droite du premier instantané d'écran ci-dessus, et vous pouvez voir où cette référence forte a été initialement établie:

code

La technique de diagnostic de la mémoire ci-dessus (et plus) est illustrée dans la dernière partie de WWDC 2016 débogage visuel avec Xcode .


La technique traditionnelle des instruments (particulièrement utile si vous utilisez des versions plus anciennes de Xcode) est décrite ci-dessous, dans ma réponse originale.


Je suggère d'utiliser l'outil "Allocations" d'Instruments avec la fonction "Record Reference Counts":

record reference counts

Vous pouvez ensuite exécuter l'application dans Instruments, puis rechercher votre classe dont vous savez qu'elle fuit et explorer en cliquant sur la flèche:

enter image description here

Vous pouvez ensuite explorer les détails et consulter la trace de la pile à l'aide du panneau "Détails étendus" à droite:

extended details

Dans ce panneau "Détails détaillés", concentrez-vous sur votre code en noir plutôt que sur les appels système en gris. Quoi qu'il en soit, à partir du panneau "Détails étendus", vous pouvez ensuite explorer votre code source, directement dans Instruments ::

your code

Pour plus d'informations et de démonstrations sur l'utilisation d'Instruments pour détecter les problèmes de mémoire, veuillez consulter:

112
Rob

Utilisez des instruments pour vérifier les fuites et les pertes de mémoire dues à la mémoire conservée mais pas à la fuite. Ce dernier est la mémoire inutilisée qui est toujours indiquée. Utilisez Mark Generation (Heapshot) dans l'instrument Allocations sur les instruments.

Pour savoir comment utiliser Heapshot pour trouver un creap de mémoire, voir: blog bbum

Fondamentalement, la méthode consiste à exécuter l'outil d'allocation d'instruments, à prendre un heapshot, à exécuter une itération de votre code et à prendre un autre heapshot en répétant 3 ou 4 fois. Cela indiquera la mémoire allouée et non libérée pendant les itérations.

Pour comprendre les résultats divulguer pour voir les allocations individuelles.

Si vous avez besoin de voir où les retenues, les versions et les versions automatiques se produisent pour un objet, utilisez les instruments:

Exécutez dans les instruments, dans Allocations, activez "Enregistrer les comptes de référence" (pour Xcode 5 et inférieur, vous devez arrêter l'enregistrement pour définir l'option). Faites fonctionner l'application, arrêtez l'enregistrement, effectuez une exploration vers le bas et vous pourrez voir où toutes les conservations, versions et autoreleases se sont produites.

2
zaph