95 votes

ViewController respondsToSelector : message envoyé à l’instance libérée (CRASH)

Ok, voici l'affaire, je déteste mettre des questions sur mon débogage et les accidents. Parce que j'ai l'habitude de gérer moi-même, mais j'ai juste ne peut pas obtenir mon chemin autour de cela, même après l'affichage de plusieurs questions déjà.

Ok, donc voici le problème, j'ai trouver mon application de façon aléatoire sur et hors de la plante avec cette trace de la pile:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

ViewController peut varier, parfois, le lieu où mon code se bloque, n'a PAS de pertinence à particulier ViewController et n'est pas propriétaire ou l'appeler.

Aussi, pour obtenir que la console de trace, je l'ai activé sur les Zombies, sinon je ne reçois pas de console d'impression à tous, je ne vous: objc_msgSend, ce qui je sais que je suis de messagerie quelque chose qui est publié. Mais je ne trouve pas où c'est... je suis vraiment coincé! Habituellement, j'ai toujours debug mes plantages, donc je suis vraiment bloqué sur ce.

Encore une fois, cette plante dans des endroits différents, à des moments différents, sur et en dehors. Et l'endroit où il se bloque a presque pas de pertinence à l' ViewController. Et je trouve cela très confus.

Avez-vous besoin de mon code? J'ai un lot de fichiers et puisque c'est de s'écraser dans des endroits différents, la distribution de mon code sera un gâchis!

J'ai essayé d'ajouter de la symbolique des points d'arrêt avec pas de chance, et les Zombies ne sont pas disponibles sur les Instruments de l'application pour iOS. Je ne peux pas lancer mon application sur le simulateur comme il est indifférent à l'architecture cadre.

Merci à tout le monde...

169voto

Johnnywho Points 3058

Utiliser des Instruments pour traquer libéré instance erreurs. Le profil de votre application (Cmd ⌘+I) et de choisir les Zombies modèle. Après que votre demande est en cours d'exécution, essayez de crash. Vous devriez obtenir quelque chose comme ça:

enter image description here

Cliquez sur la flèche à côté de l'adresse dans la liste de montrer l'objet qui a été appelé après qu'il a été libéré.

enter image description here

Vous devriez voir maintenant, à chaque appel, qui a changé de conserver compter de cet objet. Ce pourrait être parce que l'envoi directement à retenir/libération des messages ainsi que le drainage autorelease piscines ou les insérer dans NSArrays.

RefCt colonne montre retainCount après l'action a été invoqué et Responsable de l'Appelant indique nom de la classe et de la méthode dans laquelle elle a été effectuée. Lorsque vous double-cliquez sur n'importe quel retenir/release, instruments va vous montrer la ligne de code où cela a été effectuée (Si cela ne fonctionne pas, vous pouvez examiner l'appel en la sélectionnant et en choisissant son homologue Étendu Détail volet):

enter image description here

Cela vous permettra d'examiner tous les retainCount du cycle de vie de l'objet et probablement, vous trouverez votre problème immédiatement. Tous vous avez à faire est de trouver manquant conserver pour la dernière version.

59voto

software evolved Points 2125

a eu un problème similaire. Dans mon cas, un viewController nécessaire pour obtenir navigationController événements, c'était donc l'enregistrement en tant que la manette de navigation délégué:

 self.navigationController.delegate = self;

Le crash se produit lorsque le contrôleur a été dealloc ed mais était encore le délégué de l'-vue-contrôleur. L'ajout de ce code dans le dealloc a eu aucun effet:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

parce que au point que dealloc est appelé, la vue contrôleur a déjà été retiré de la vue de la hiérarchie, donc de soi.navigationController est nul, donc la comparaison est voué à l'échec! :-(

La solution était d'ajouter ce code pour détecter la VC de quitter le point de vue de la hiérarchie de juste avant qu'elle ne fait. Il utilise une méthode introduit dans l'iOS 5 pour déterminer quand la vue est pop ed et ne les pousse pas

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

Ne plante plus!

4voto

Zack Morris Points 560

Pour quelqu'un qui ne peut pas le résoudre, voici quelques autres techniques:

http://stackoverflow.com/a/12264647/539149

http://stackoverflow.com/a/5698635/539149

http://stackoverflow.com/a/9359792/539149

http://stackoverflow.com/a/15270549/539149

http://stackoverflow.com/a/12098735/539149

Vous pouvez exécuter des Instruments dans Xcode 5 en cliquant sur le projet popup->Modifier le Régime...Profil ->Instrument et choisir les Affectations ou les Fuites, puis le profil de votre application, puis arrêter Instruments, cliquez sur le bouton info de la répartition et de "Permettre NSZombie de Détection".

Toutefois, pour les messages qui proviennent directement de la com.apple.principal-thread, ce ne sera probablement pas révéler quoi que ce soit.

Je me suis cogné la tête sur ce pendant plus de deux heures et la réponse s'est avéré être une libération, que j'ai découvert en commentant une copie de mon projet par la force brute jusqu'à ce que j'ai trouvé le coupable:

[viewController release];
viewController = NULL;

Le problème est que la libération n'a pas défini la variable à NULL.

Cela signifie que le paramètre NULL appels libérer à nouveau, la décrémentation de la refcount et de libérer de la mémoire, jusqu'à ce que plus tard, lorsque les variables de référence viewController sont finis avec elle.

Donc, soit de permettre à l'ARC ou assurez-vous que votre projet utilise systématiquement la libération ou la valeur NULL, mais pas les deux. Ma préférence est d'utiliser la valeur NULL, car alors il n'y a aucune chance de référencement d'un zombie, mais il permet aussi de trouver où les objets sont libérés plus difficile.

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