80 votes

Comment trouver la cause d'une erreur "double free" chez malloc?

Je suis programmation d’une application en Objective-C et j’obtiens cette erreur :

Il se passe lorsque je libère un NSAutoreleasePool et je ne peux pas savoir quel objet je suis libérer deux fois.

Comment définir son point d’arrêt ?

Y a-t-il un moyen de savoir ce qu’est cet « objet 0x1068310 » ?

Merci d’avance

Gonso

46voto

Quinn Taylor Points 29688

Lorsqu'un objet est "double-libéré", la cause la plus commune est que vous êtes (inutilement) la publication d'une autoreleased objet, et c'est plus tard autoreleased lorsque le contenant autorelease pool est vidé.

J'ai trouvé que la meilleure façon de traquer la version supplémentaire est l'utilisation de la NSZombieEnabled variable d'environnement pour le fichier exécutable dans Xcode. Pour un rapide aperçu de la façon de l'utiliser, découvrez cette CocoaDev page wiki. (En plus de cette page, Apple a documenté des incroyablement obscur mais des conseils utiles pour le débogage de code dans Xcode, certains ont sauvé ma bacon plus de quelques fois. Je suggère de vérifier cette Note Technique sur developer.apple.com - enchaîner les sauts à la section sur le Cacao de la Fondation du cadre).

Edit: Vous pouvez souvent le suivi de l'objet concerné dans le cadre de l'Xcode débogueur, mais il est souvent beaucoup plus facile si vous utilisez des Instruments pour vous aider. À partir de Xcode, choisissez Exécuter → Démarrer Avec la Performance de l'Outil → Allocations d'Objets et vous devriez être en mesure de retracer l'objet concerné retour à l'endroit où il a été créé. (Cela fonctionnera mieux si vous avez activé les zombies comme discuté ci-dessus.) Remarque: Snow Leopard ajoute un Zombies outil d'Instruments, accessible depuis le menu Exécuter. Peut-être vaut le $29 seul! ;-)

Il y a également une SI la question ici.

37voto

Frank Krueger Points 27508

Vous découvrirez ce qu'est l'objet lorsque vous ouvrez le débogueur. Il suffit de regarder la pile d'appels et vous trouverez où vous la libérez. Cela vous dira de quel objet il s'agit.

Le moyen le plus simple de définir le point d'arrêt consiste à:

  1. Aller à Exécuter -> Afficher -> Points d'arrêt ( ALT - Command - B )
  2. Faites défiler la liste jusqu'en bas et ajoutez le symbole malloc_error_break

12voto

Hoang Pham Points 4061

Je veux juste ajouter mon expérience, en plus de la réponse de Taylor Quinn.

Dans une de mes applications, j'ai d'analyser et d'enregistrer les données dans la base de données des objets et, plus tard, avoir ces objets à afficher dans la vue. En fait, l'application fonctionne très bien et ne tombe pas en panne à tous, jusqu'à ce que j'ai essayé de faire un test de stress de la navigation en arrière et en avant à plusieurs reprises, essayé d'ouvrir plusieurs points de vue aussi vite que possible. L'application se bloque avec le message ci-dessus.

J'ai essayé toutes les méthodes que Quinn suggère dans sa réponse et toujours pas réussi à trouver où est la cause exacte.

J'ai mis NSZombieEnabled=OUI, et NSStackLogging=OUI, l'exécution de la commande shell malloc_history de savoir pourquoi, mais toujours pas de chance. Il indique toujours à l'endroit où je enregistrer les données dans la base de données des objets, en fait, j'ai vérifié mille fois plus d'objets publiés là, rien de bizarre.

Cours d'exécution dans les Instruments avec divers outils(Allocations, Fuites, etc...) n'a toujours pas aider. Activer la Garde Malloc reste encore de rien.

Sauvetage Final: j'ai essayé de revenir à la vue, où les objets ont été prises à partir de Données de Base et envoyé conserver un message à tous ces objets, et a pris note de ces changements. Il a résolu le problème!!!

Donc, j'ai trouvé que je n'ai pas réussi à conserver un titre, c'est exactement la cause. Juste envie de partager mon expérience si vous avez un autre de secours pour votre application.

9voto

Adam Rosenfield Points 176408

Ouvrir le débogueur de la console en appuyant sur Cmd+Maj+R. Il y, type de

break malloc_error_break

pour définir un point d'arrêt au début de l' malloc_error_break fonction.

Si vous voulez savoir quel objet est situé à l'adresse 0x1068310, vous pouvez tapez la commande suivante dans la console du débogueur:

print-object 0x1068310

Bien sûr, vous avez à faire cela, tandis que l'objet est toujours en vie, si l'objet a déjà été libérée au moment où vous le faites, alors cela ne fonctionnera pas.

4voto

c-alpha Points 31

Pour moi, le problème a été résolu par

 (gdb) call (void)_CFAutoreleasePoolPrintPools()
 

juste après l'accident. L'adresse en haut de la pile était l'adresse du coupable. Jeté dans un retain et le tour est joué.

L'adresse donnée dans le message du journal ne m'a pas conduit nulle part. Il ne s'est jamais retrouvé dans aucun des différents Instrumets. Apparemment, un pointeur sur des données internes déjà libérées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X