2010-09-17 20 views
3

Récemment, je reçois des rapports d'erreurs intermittentes de mon application prétendant « sélecteur non reconnu » dans les zones qui ne pourrait leur causer, et pourtant ils le font.Obtenir étranges intermittents exceptions « sélecteur non reconnu » dans l'application iPhone

Par exemple, celui-ci:

Error: NSInvalidArgumentException: *** -[NSCFString didReceiveMemoryWarning]: unrecognized selector sent to instance 0x541fe0 
0 CoreFoundation      0x32de1e23 __handleUncaughtException + 230 
1 libobjc.A.dylib     0x3266d894 _objc_terminate + 156 
2 libstdc++.6.dylib     0x338c3a8c _ZN10__cxxabiv111__terminateEPFvvE + 84 
3 libstdc++.6.dylib     0x338c3b04 _ZSt9terminatev + 24 
4 libstdc++.6.dylib     0x338c3c2c __cxa_throw + 108 
5 libobjc.A.dylib     0x3266be5c objc_exception_throw + 112 
6 CoreFoundation      0x32de2bfd -[NSObject doesNotRecognizeSelector:] + 112 
7 CoreFoundation      0x32d67b19 ___forwarding___ + 480 
8 CoreFoundation      0x32d5e840 _CF_forwarding_prep_0 + 48 
9 Foundation       0x33f765d9 _nsnote_callback + 184 
10 CoreFoundation      0x32d9e511 _CFXNotificationPostNotification + 304 
11 Foundation       0x33f741b3 -[NSNotificationCenter postNotificationName:object:userInfo:] + 70 
12 Foundation       0x33f76519 -[NSNotificationCenter postNotificationName:object:] + 20 
13 UIKit        0x30d18db8 -[UIApplication _performMemoryWarning] + 68 
14 UIKit        0x30d18d50 -[UIApplication _receivedMemoryNotification] + 136 
15 UIKit        0x30d18c80 _memoryStatusChanged + 64 
16 CoreFoundation      0x32d66eb7 __CFNotificationCenterDarwinCallBack + 26 
17 CoreFoundation      0x32d5cb51 __CFMachPortPerform + 78 
18 CoreFoundation      0x32da452b CFRunLoopRunSpecific + 2302 
19 CoreFoundation      0x32da3c1f CFRunLoopRunInMode + 50 
20 GraphicsServices     0x31bb9374 GSEventRunModal + 196 
21 UIKit        0x30bf3c30 -[UIApplication _run] + 560 
22 UIKit        0x30bf2230 UIApplicationMain + 968 
23 Mind        0x00002c68 main + 72 
24 Mind        0x00002be4 start + 52 

Ceci est le système d'exploitation l'envoi d'un avertissement de mémoire à mon application, et en quelque sorte la classe d'application a changé en une chaîne.

Il semble se produire beaucoup plus lorsque le code est invoqué par un NSOperation:

Error: NSInvalidArgumentException: -[NSCFString setObject:forKey:]: unrecognized selector sent to instance 0x3e793088 
9 Mind        0x0015de70 -[CCTextureCache textureFromFile:] + 528 
10 Mind        0x0015d9f4 -[CCTextureCache loadImageUncached:pixelFormat:] + 116 
11 Mind        0x0015d058 -[CCTextureCache addImage:pixelFormat:] + 152 
12 Mind        0x00080524 -[ImageLoader imageWithFile:pixelFormat:] + 84 
13 Mind        0x000854c4 -[ImageLoadOperation performLoad] + 68 
14 Mind        0x00085800 -[ResourceLoadOperation main] + 112 
15 Foundation       0x30c4c8b5 -[__NSOperationInternal start] + 664 
16 Foundation       0x30c4c613 -[NSOperation start] + 22 
17 Foundation       0x30cbdb63 ____startOperations_block_invoke_2 + 46 
18 libSystem.B.dylib     0x31227858 _dispatch_call_block_and_release + 20 
19 libSystem.B.dylib     0x3122863c _dispatch_worker_thread2 + 128 
20 libSystem.B.dylib     0x311b1544 _pthread_wqthread + 400 
21 libSystem.B.dylib     0x311a8b74 __stack_chk_fail + 4294967295 

Le code en question est:

[textures setObject: texture forKey: nom de fichier];

textures est de type NSMutableDictionary * et n'est jamais réaffectés ou désallouée (naturellement, car cela est un objet de cache). C'est le seul endroit où setObject est invoqué dans cette méthode, mais selon la trace de la pile, textures était une chaîne.

Je reçois aussi cette bizarrerie:

Error: NSInvalidArgumentException: -[NSConcreteNotification getPixelFormatForIdentifier:]: unrecognized selector sent to instance 0x5c021b0 
9 Mind        0x0015dd0c -[CCTextureCache textureFromFile:] + 172 
10 Mind        0x0015d9f4 -[CCTextureCache loadImageUncached:pixelFormat:] + 116 
11 Mind        0x0015d058 -[CCTextureCache addImage:pixelFormat:] + 152 
12 Mind        0x00080524 -[ImageLoader imageWithFile:pixelFormat:] + 84 
13 Mind        0x000854c4 -[ImageLoadOperation performLoad] + 68 
14 Mind        0x00085800 -[ResourceLoadOperation main] + 112 
15 Foundation       0x347b78b5 -[__NSOperationInternal start] + 664 
16 Foundation       0x347b7613 -[NSOperation start] + 22 
17 Foundation       0x34828b63 ____startOperations_block_invoke_2 + 46 
18 libSystem.B.dylib     0x32a2f858 _dispatch_call_block_and_release + 20 
19 libSystem.B.dylib     0x32a3063c _dispatch_worker_thread2 + 128 
20 libSystem.B.dylib     0x329b9544 _pthread_wqthread + 400 
21 libSystem.B.dylib     0x329b0b74 __stack_chk_fail + 4294967295 

Cette trace est le code suivant dans CCTextureCache:

CCTexture2DPixelFormat PixelFormat = [self getPixelFormatForIdentifier: identifiant];

Comment CCTextureCache changé en NSConcreteNotification après avoir déjà appelé un certain nombre de méthodes sur lui-même est pour le moins déroutant.

Quelqu'un at-il remarqué ce genre de chose? Suis-je en train d'obtenir une corruption de la mémoire?

Répondre

1

Avez-vous vérifié certaines conditions de course à propos de multi-threads? Il semble que certaines ressources soient libérées par un autre thread, et le thread actuel envoie un message à un objet désalloué.

Error: NSInvalidArgumentException: -[NSCFString setObject:forKey:]: unrecognized selector sent to instance 0x3e793088 
9 Mind        0x0015de70 -[CCTextureCache textureFromFile:] + 528 
10 Mind        0x0015d9f4 -[CCTextureCache loadImageUncached:pixelFormat:] + 116 
11 Mind        0x0015d058 -[CCTextureCache addImage:pixelFormat:] + 152 
12 Mind        0x00080524 -[ImageLoader imageWithFile:pixelFormat:] + 84 
13 Mind        0x000854c4 -[ImageLoadOperation performLoad] + 68 
14 Mind        0x00085800 -[ResourceLoadOperation main] + 112 
15 Foundation       0x30c4c8b5 -[__NSOperationInternal start] + 664 
16 Foundation       0x30c4c613 -[NSOperation start] + 22 
17 Foundation       0x30cbdb63 ____startOperations_block_invoke_2 + 46 
18 libSystem.B.dylib     0x31227858 _dispatch_call_block_and_release + 20 
19 libSystem.B.dylib     0x3122863c _dispatch_worker_thread2 + 128 
20 libSystem.B.dylib     0x311b1544 _pthread_wqthread + 400 
21 libSystem.B.dylib     0x311a8b74 __stack_chk_fail + 4294967295 
+0

Le fait est que les objets qui sont écrasés sont des singletons qui ont déjà existé pendant longtemps (Dans le troisième exemple que j'ai cité, la classe d'objet singleton est écrasée PENDANT qu'il y a 3 niveaux profonds dans les appels auto-référencés). Une condition de concurrence ne peut que provoquer des allocs pour remplacer les autres allocs qui se produisent très près les uns des autres dans différents threads. Il ne remplacerait pas les objets établis depuis longtemps. Il semble que ce devrait être un pointeur indésirable quelque part, mais il est étrange que la corruption de la mémoire mène toujours à un descripteur de classe d'objet valide. – Karl

+0

À la 16. Je vois NSOperation démarrer, donc je suppose qu'il fonctionne sous multi-threads. – AechoLiu

+0

Et les textures signifient la texture OpenGL-ES? L'OpenGL-ES peut-il fonctionner sous un environnement multi-thread? – AechoLiu

0

Cela est souvent causé par des erreurs de gestion de la mémoire. Avez-vous essayé zombies?

... avec des zombies activés, des messages à des objets désallouées ne seront plus se comporter étrangement ou accident dans des conditions difficiles à comprendre les moyens, mais seront plutôt enregistrer un message et mourir d'une manière prévisible et breakpointable débogueur . Il s'agit de l'outil à utiliser lorsque vous tentez de rechercher les versions supérieures et les versions prématurées.

+0

Cette application est dans l'App Store pour le moment. Sur quelques milliers d'utilisateurs, je reçois un rapport d'erreur de cette sorte tous les quelques jours. Je n'ai pas rencontré de zombie dans mon environnement de développement. – Karl

+5

Suis-je le seul qui trouve "Je n'ai pas rencontré un zombie dans mon environnement de développement." drôle? –

+0

Je n'ai pas étudié vos échantillons trop longtemps, mais de tels bogues sont généralement assez pénibles à déboguer. Essayez l'analyseur statique, vérifiez votre gestion de la mémoire, affirmez autant que possible, libérez les références et activez les zombies dans les builds de débogage :) – zoul

0

Je viens de rencontrer le même problème, mais il se trouve que je l'avais fait une erreur stupide:

j'avais déclaré un membre comme celui-ci dans le fichier d'en-tête:

NSMutableDictionary* myDict; 

Mais puis initialisé comme ça dans le.fichier m:

myDict = [[NSDictionary alloc] init]; 

qui est valide et tout, parce que le NSMutableDictionary est dérivé de la classe NSDictionary. Par conséquent, tous les appels hérités de NSDictionary ont réellement fonctionné, mais les appels spécifiques à NSMutableDictionary [setObject: forKey:] ont échoué car j'ai tenté de les invoquer sur la classe parente.

L'erreur était vraiment bête, mais j'ai aussi été rebuté par le fait que le débogueur a rapporté le type de myDict comme quelque chose de totalement différent (ni NSDictionary, ni NSMutableDictionary). J'espère que cela aide un autre codeur fatigué :-)