Une erreur de selector bien étrange
Greensource
Membre
Coucou.
J'ai une erreur bizarre pendant l'execution. C'est une Exception du à un objet qui ne peut répondre à un selecteur:
Sauf que je suis sur de ne jamais envoyer le message "isDead" à un objet de type NSCFType, je ne sais même pas ce que c'est. D'autant que parfois j'ai la même erreur mais sur un UIColor???
Vous avez une idée de ce j'ai pu faire pour provoquer ça?
J'ai une erreur bizarre pendant l'execution. C'est une Exception du à un objet qui ne peut répondre à un selecteur:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFType isDead]: unrecognized selector sent to instance 0x5513f0'
Sauf que je suis sur de ne jamais envoyer le message "isDead" à un objet de type NSCFType, je ne sais même pas ce que c'est. D'autant que parfois j'ai la même erreur mais sur un UIColor???
Vous avez une idée de ce j'ai pu faire pour provoquer ça?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Une fois que tu as mis ce code et le point d'arrêt sur la ligne indiquée, tu lances ton programme en mode Debug (Pomme-Y), et il devrait s'arrêter sur le point d'arrêt quand il essaye d'envoyer le message "isDead". Et là dans le débogueur tu pourras alors avoir la "callstack", c'est à dire la pile des appels de méthodes... tu pourras alors voir quelle méthode a appelé cette méthode isDead, et quelle méthode a appelé cette méthode, et remonter jusqu'à la ligne de ton code qui a déclenché tous ces appels en série... restera plus qu'à comprendre pourquoi cette ligne de ton code déconne et génère cet appel qui fait tout planter.
Ceci dit vu le problème, m'est avis que tu gardes quelque part dans une variable un objet qui a été releasé entre temps. Du coup ta variable qui pointait avant sur ton objet pointe maintenant sur du n'importe quoi, du coup quand tu envoies un message à cette variable ça part en cou... en vrille.
Plus d'infos ici.
Je me doutais que c'était une histoire d'Objet releasé trop tôt.
J'ai essayer NSZombi, j'ai fait NSZombiEnabled=YES dans le terminal mais ça change rien. Je lirais plus attentivement la doc.
Je vois tout ça et je vous redit, merci.
[edit] Bon en fait j'ai regarder, ça doit-être ça puisque maintenant j'ai le message:
Je vais continuer mes recherches.
En tout cas merci, vraiment pas mal vos techniques
Pour fixer une variable d'environnement:
- Dans l'onglet Targets, sélectionne l'exécutable
- Menu File > Get Info > Onglet Arguments
En bas, tu as la liste des variables d'environnement.
- Crée la variable NSZombieEnabled, mets sa valeur à YES.
- Evidemment, coche-là .
Fais juste gaffe, si NSZombie est activé, les objets restent en mémoire, pense donc à décocher la case dès que tu n'en as plus besoin.
Suffit d'ajouter à la main le point d'arrêt "-[NSCFType isDead]"...
ça fait vraiment message interne de GC qui cherche à savoir si un objet n'a plus aucune référence.
Et du coup j'ai bien ce message envoyé à une case libéré (d'être une case libéré, tu sais c'est pas si facile.Ne la laisse pas tombé, elle est si fragile... humhum dsl :P)
Du coup c'est probablement un problème de mémoire... Un objet libéré, sa structure objet a été remplacée par un objet NSCF alloué à la même place mémoire... et paf.
Tu as passé ton truc à la moulinette CLANG ?
Ah bas si je crois que je comprends ma bêtise, j'ai mi l'affectation dans le if! C'est ça non?
Sinon j'appel le setter comme ceci:
C'est ok, ça? Faut bien un retain n'est-ce pas?
[edit] J'ai une petit question supplémentaire: Ali, dans la méthode que tu m'as donné pour ajouter une méthode à NSObject: Ca signifie quoi le @interface NSObject(Debug)? Ce qu'il y a entre parenthèse?
Les retain / release doivent être équilibrés dans les accesseurs.
J'aime pas trop ce "if" inutile à 99,99 % des cas sinon, je trouve cette technique plus simple et plus élégante :
Il s'agit d'une catégorie, ça fait partie des possibilités offertes par le langage Objective-C pour étendre les possibilités d'une classe déjà existante... qui peut s'avérer très pratique
En l'occurrence j'ajoute une méthode à la classe existante NSObject (et donc aussi à toutes les classes dérivant de NSObject, autrement dit toutes les classes de Cocoa en fait) la méthode que tu sembles essayer d'appeler. S'il y a des sous-classes de NSObject qui implémentent cette méthode, ça va la surcharger donc pas de soucis... par contre toutes les autres classes qui à la base n'implémentent pas cette méthode, bah en rajoutant la catégorie ça va permettent qu'ils y répondent via cette catégorie, et là du coup en mettant le breakpoint dessus, tu récupères tous ces cas là (les cas où la méthode est appellée sur un NSObject qui à la base n'implémentais pas la méthode).
Pour plus d'infos un peu de lecture : http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html
Le souci avec les pointeurs c'est qu'à la Fac on a commencer par Java, et je pense que ça nous a beaucoup desservi finalement, à cause de ça. J'ai toujours l'impression que c'est pas si important la gestion de la mémoire alors que ça semble primordial au contraire.
Puis en fait, il peut y rester, même une fois l'apprentissage terminé :P