web-dev-qa-db-fra.com

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

Je programme une application dans Objective-C et j'obtiens cette erreur:

MyApp (2121,0xb0185000) malloc: *** erreur pour l'objet 0x1068310: double libre
*** définir un point d'arrêt dans malloc_error_break pour déboguer

Cela se produit lorsque je libère un NSAutoreleasePool et je ne peux pas comprendre quel objet je libère deux fois.

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

Existe-t-il un moyen de savoir quel est cet "objet 0x1068310"?

80
gonso

Vous découvrirez ce qu'est l'objet lorsque vous interrompez le débogueur. Recherchez simplement 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 est de:

  1. Allez dans Exécuter -> Afficher -> Points d'arrêt (ALT-Command-B)
  2. Faites défiler vers le bas de la liste et ajoutez le symbole malloc_error_break
37
Frank Krueger

Lorsqu'un objet est "à double libération", la cause la plus courante est que vous libérez (inutilement) un objet libéré automatiquement, et il est ensuite libéré automatiquement lorsque le pool de libération automatique contenant est vidé.

J'ai trouvé que la meilleure façon de retrouver la version supplémentaire est d'utiliser la variable d'environnement NSZombieEnabled pour l'exécutable affecté dans Xcode. Pour un aperçu rapide de la façon de l'utiliser, consultez cette page wiki CocoaDev . (En plus de cette page, Apple a documenté des conseils incroyablement obscurs mais utiles pour déboguer du code dans Xcode, dont certains ont sauvé mon bacon plusieurs fois. Je suggère de vérifier - cette note technique sur developer.Apple.com - le lien passe à la section sur le framework Cocoa's Foundation).

Edit: Vous pouvez souvent suivre l'objet incriminé dans le débogueur Xcode, mais c'est souvent beaucoup plus facile si vous utilisez des instruments pour vous aider. Dans Xcode, choisissez Exécuter → Démarrer avec l'outil de performance → Allocations d'objets et vous devriez pouvoir retracer l'objet incriminé jusqu'à l'endroit où il a été créé. (Cela fonctionnera mieux si vous avez activé les zombies comme indiqué ci-dessus.) Remarque: Snow Leopard ajoute un outil Zombies aux instruments, accessible depuis le menu Exécuter ainsi que. Peut-être vaut-il seulement les 29 $! ;-)

Il y a aussi une connexe SO question ici .

45
Quinn Taylor

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

Dans l'une de mes applications, je dois analyser et enregistrer des données dans des objets de données de base, puis obtenir ces objets à afficher sur les vues. En fait, l'application fonctionne très bien et ne se bloque pas du tout, jusqu'à ce que j'essaie de faire un test de stress pour naviguer plusieurs fois dans les deux sens, j'ai essayé d'ouvrir plusieurs vues aussi rapidement que possible. L'application se bloque avec le message ci-dessus.

J'ai essayé toutes les méthodes suggérées par Quinn dans sa réponse et je n'ai toujours pas trouvé la cause exacte.

J'ai défini NSZombieEnabled = YES et NSStackLogging = YES, j'ai exécuté la commande Shell malloc_history pour savoir pourquoi, mais toujours pas de chance. Il indique toujours où j'enregistre les données dans des objets de données de base, en fait, j'ai vérifié des milliers de fois les objets libérés là-bas, rien d'étrange.

L'exécution d'instruments avec divers outils (allocations, fuites, etc.) n'a toujours pas aidé. Activer la garde Malloc n'a toujours rien obtenu.

Sauvetage final: J'ai essayé de revenir aux vues où les objets ont été extraits de Core Data et j'ai envoyé un message de conservation à tous ces objets, et j'ai pris note de ces changements. Cela a résolu le problème !!!

Donc, j'ai découvert que je n'ai pas réussi à en conserver un, c'est exactement la cause. Je veux juste partager mon expérience pour que vous ayez un autre sauvetage pour votre application.

12
Hoang Pham

Ouvrez la console du débogueur en appuyant sur Cmd + Maj + R. Là, tapez

break malloc_error_break

pour définir un point d'arrêt au début du malloc_error_break une fonction.

Si vous souhaitez savoir quel objet se trouve à l'adresse 0x1068310, vous pouvez taper ce qui suit dans la console de débogage:

print-object 0x1068310

Bien sûr, vous devez le faire pendant que l'objet est encore vivant - si l'objet a déjà été libéré au moment où vous le faites, cela ne fonctionnera pas.

9
Adam Rosenfield

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

(gdb) call (void)_CFAutoreleasePoolPrintPools()

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

L'adresse indiquée dans le message du journal ne m'a conduit nulle part. Il n'est jamais apparu dans aucun des différents Instrumets. Apparemment, un pointeur vers certaines données internes qui avaient déjà été libérées.

4
c-alpha

Ajout d'un point d'arrêt symbolique dans Xcode 4

Juste une mise à jour pour rendre cela pertinent pour Xcode 4 ...

Depuis le Guide de l'utilisateur Xcode 4 :

Pour ajouter un point d'arrêt symbolique. . .

  1. Dans le coin inférieur gauche du navigateur de points d'arrêt, cliquez sur le bouton Ajouter.
  2. Choisissez Ajouter un point d'arrêt symbolique.
  3. Saisissez le nom du symbole dans le champ Symbole.
  4. Cliquez sur Terminé.
4
Old McStopher

Voici à quoi ressemble le point d'arrêt malloc_error_break dans la fenêtre Points d'arrêt dans Xcode. Besoin de cocher les cases pour le faire fonctionner.

texte alternatif http://www.martijnthe.nl/wp-content/uploads/2009/08/Afbeelding-1.png

3
Martijn Thé

Vérifiez vos classes et regardez sous la méthode dealloc. N'oubliez pas d'appeler [super dealloc].

J'ai eu exactement le même problème et j'ai découvert que j'appelais [self dealloc] au lieu. Je ne fais juste pas attention.

2
Wes Duff

Veuillez trouver les étapes ci-dessous pour savoir comment trouver l'objet qui est gratuit et planter l'application.

1) Cliquez sur " Navigateur de points d'arrêt".
2) Cliquez ensuite sur le bouton " +" ci-dessous.
3) Ajoutez le " Symbolic Breakpoint ..." dans la liste.
4) Ajoutez le mot clé " malloc_error_break" sur l'option " Symbol".

Ou vous pouvez également consulter la présentation GIF ci-dessous.

GIF represenation

2

Cela est généralement causé par un inspecteur, tel qu'un safari ou un aperçu de safari. Reportez-vous à post ou post et question .

Supprimer la sélection de Afficher automatiquement le Web ...., supprimera ce problème.

Remarque, il suffit de fermer le safari ou l'aperçu du safari pour ne pas supprimer ce problème. Et vous devez désélectionner à la fois le safari et l'aperçu du safari.

Si cela ne fonctionne pas, reportez-vous à ceci réponse ou post pour le déboguer.

deselect automatically inspect on safari preview

1
Kris Roofe

Dans Xcode, cliquez à gauche du numéro de ligne pour définir un point d'arrêt. Ensuite, vous pouvez le lancer en faisant un "Build and Debug".

Il est recommandé de ne pas avoir d'objet que vous créez soit autorelease car la mémoire est une marchandise sur l'iPhone. Apple recommande d'appeler explicitement release.

0
Benny Wong

Pour trouver ces types de problèmes de mémoire et de pointeur en général, vous souhaitez exécuter votre code par rapport à un vérificateur d'erreur de mémoire d'exécution comme Valgrind . Cela devrait être en mesure de signaler de nombreuses choses que votre code fait mal, au-delà de celles qui le font planter.

Valgrind peut fonctionner sur OSX (même s'il dit que c'est "non pris en charge et incomplet et buggé"), et avec un peu de piratage, quelqu'un l'a fait fonctionner exécutables du SDK iPhone .

Encore mieux, vous pouvez essayer Instruments, qui fait partie de XCode. Il y a un tutoriel pour l'exécuter ici .

0
Jared Oberhaus

Si malloc_error_break n'aide pas ...

La meilleure façon de résoudre cette erreur est d'exécuter instruments avec le NSZombies activé. Les instruments vous signalent lorsque le Zombie est envoyé et vous pouvez remonter directement à la ligne de code.

Snow Leopard requis, quelle bouée de sauvetage cependant!

0
iOSDevSF