Je suis nouveau sur le développement de l’iPhone et sur XCode en général et je ne sais pas comment commencer à dépanner un signal EXC_BAD_ACCESS
. Comment puis-je obtenir que XCode se casse à la ligne exacte à l’origine de l’erreur?
Je n’arrive pas à faire en sorte que XCode s’arrête sur la ligne à l’origine du problème, mais je vois les lignes suivantes dans ma console de débogage:
Dim Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetStrokeColorWithColor: contexte invalide
Dim Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetLineWidth: contexte invalide
- Comment déboguer efficacement avec spyder en Python?
- est-il possible de “revenir en arrière” dans le débogueur d’éclipse de java comme en faisant glisser la flèche dans VS
- utiliser ipdb pour déboguer du code python dans une cellule (jupyter ou ipython)
- (Android Studio) Comment déboguer via mon code uniquement?
- «Erreur interne dans l’évaluateur d’expression»
Sun Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextAddPath: contexte invalide
Dim Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextDrawPath: contexte invalide
2009-10-25 15: 12: 14.680 LanderTest [1289: 207] *** – [CFArray objectAtIndex:]: message envoyé à l’instance désallouée 0x3c4e610
J’essaie maintenant de dessiner dans le contexte que je récupère depuis UIGraphicsGetCurrentContext()
et de passer à l’object avec lequel je veux dessiner.
Débogage plus approfondi des essais et des erreurs et j’ai trouvé qu’un NSMutableArray
lequel j’avais une propriété dans ma classe était un zombie. Je suis allé dans la fonction init
pour la classe et voici le code que j’utilisais:
if ((self = [super init])) { NSMutableArray *array = [NSMutableArray array]; self.terrainBlocks = array; [array release]; } return self; }
J’ai supprimé la ligne [array release]
et elle ne me donne plus le signal EXC_BAD_ACCESS
, mais je ne comprends plus pourquoi cela fonctionne. Je pensais que lorsque j’utilisais la propriété, elle la conservait automatiquement pour moi et que je devais donc la libérer de init
afin de ne pas avoir de fuite. Je suis complètement perplexe quant à la façon dont cela fonctionne et tous les guides et questions Stackoverflow que j’ai lus seulement me confondent davantage sur la façon de définir les propriétés dans ma méthode init. Il semble ne pas y avoir de consensus sur la meilleure façon de procéder.
Pour toute erreur EXC_BAD_ACCESS, vous essayez généralement d’envoyer un message à un object libéré. La meilleure façon de les suivre est d’utiliser NSZombieEnabled .
Cela fonctionne en ne libérant jamais réellement un object, mais en l’enveloppant comme un “zombie” et en plaçant un drapeau à l’intérieur de celui-ci qui dit qu’il aurait normalement été libéré. De cette façon, si vous essayez d’y accéder à nouveau, il sait toujours ce que c’était avant que vous ne commettiez l’erreur, et avec ce petit peu d’information, vous pouvez généralement revenir en arrière pour voir quel était le problème.
Cela aide particulièrement dans les threads d’arrière-plan lorsque le débogueur utilise parfois des informations utiles.
Il est très important de noter que vous devez vous assurer à 100% que ce n’est que dans votre code de débogage et non dans votre code de dissortingbution. Parce que rien n’est jamais sorti, votre application va fuir et fuir. Pour me rappeler de le faire, je mets ce journal dans mon appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
Si vous avez besoin d’aide pour trouver la ligne exacte, effectuez une génération et un débogage ( CMD-Y ) au lieu d’un build-and-run ( CMD-R ). Lorsque l’application plante, le débogueur va vous montrer exactement quelle ligne et en combinaison avec NSZombieEnabled, vous devriez être capable de savoir exactement pourquoi.
À propos de votre tableau. La ligne
NSMutableArray *array = [NSMutableArray array];
ne vous donne pas réellement un object conservé mais plutôt un object autorelease. Il est probablement conservé dans la ligne suivante, mais vous ne devriez pas le libérer dans la troisième ligne. Voir ça
C’est la règle fondamentale:
Vous prenez possession d’un object si vous le créez en utilisant une méthode dont le nom commence par «alloc» ou «new» ou contient «copy» (par exemple, alloc, newObject ou mutableCopy) ou si vous lui envoyez un message. Vous êtes responsable de renoncer à la propriété des objects que vous possédez en utilisant release ou autorelease. A tout autre moment où vous recevez un object, vous ne devez pas le libérer.
Dans Xcode 4, vous pouvez activer Zombies en cliquant sur le menu déroulant Scheme (en haut à gauche, juste à côté du bouton d’arrêt) -> Edit Scheme -> Onglet Diagnostics -> Enable Zombie Objects
Xcode / gdb interrompt toujours EXC_BAD_ACCESS
, il vous suffit de travailler dans la stack d’appels pour trouver le code qui l’a déclenché.
Notez que ces types d’erreurs se produisent souvent avec les objects à autoreleased
, ce qui signifie que la cause ultime du problème ne réside pas dans la stack d’appels qui a déclenché EXC_BAD_ACCESS
. C’est à ce moment que NSZombieEnabled et NSAutoreleaseFreedObjectCheckEnabled deviennent utiles.
Une nouvelle réponse à un ancien thread … dans XCode 4 Le moyen le plus efficace de diagnostiquer les exceptions EXC_BAD_ACCESS est d’utiliser Instruments pour profiler votre application (à partir de XCode, cliquez sur Product / Profile et choisissez Zombies). Cela vous aidera à identifier les messages envoyés aux objects désalloués.
A partir des classes Stanford CS193P: si vous ajoutez un point d’arrêt (manuellement, en éditant des points d’arrêt) pour le symbole objc_exception_throw
vous pouvez mieux voir ce qui ne va pas – le débogueur s’arrête de lui-même et visser la trace de la stack. Lorsque vous vous arrêtez dans objc_exception_throw, vous pouvez souvent revenir sur exactement quel access / opération a causé votre problème.
Une autre approche utile consiste à définir des points d’arrêt qui se déclenchent directement après que l’exception se soit produite:
Ouvrez la fenêtre des points d’arrêt (Run – Show – Breakpoints) et ajoutez deux points d’arrêt symboliques appelés «objc_exception_throw» et «[NSException raise]».
De: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/
Je voulais juste append pour les autres qui viennent d’un site Web, la recherche de solutions pour la même erreur, mais avec des erreurs différentes. Dans mon cas, j’ai eu la même erreur lorsque j’ai essayé d’instancier NSDictionary avec une faute de frappe dans le nom de la clé où j’ai oublié d’append “@” devant ma clé:
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];
J’espère que je n’ai pas raté une réponse identique, mais j’ai constaté qu’il était possible pour certains projets de lancer cette erreur en raison de l’exécution sur des simulateurs de versions iOS plus anciennes qui pourraient être incompatibles avec une dépendance ou un framework de projet. Je cherchais une de ces solutions depuis trop longtemps avant de réaliser que cela se passait juste dans les versions de simulateur de fichiers, comme l’iPhone 4S, que l’application n’était même pas censée essayer de prendre en charge.
J’aurais bien aimé avoir un message d’erreur plus détaillé, mais j’imagine que c’est la responsabilité du framework d’où il est originaire … En tout cas, c’est un atterrissage de recherche assez courant et cela aidera peut-être quelqu’un à faire des bêtises comme je me suis retrouvé.
Avant d’activer les zombies, je recommande d’abord de supprimer tous les avertissements (si vous en avez). Des choses simples comme une fonction non vide sans return
peuvent provoquer cette erreur. Si vous n’avez pas d’avertissement, procédez comme le suggèrent les autres réponses.