Chaque fois que mon application plante, Xcode met en surbrillance l'appel UIApicationMain () dans la fonction main () en tant que ligne ayant provoqué le blocage. Dans certains cas, cela était normal (erreur de segmentation par exemple), mais le crash que je tente de traiter est un simple SIGABRT avec des informations détaillées consignées dans la console:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: Date)'
Xcode affichait parfaitement la ligne avec les anciens SDK, mais depuis je suis passé à Xocde 4.2, cela a changé. Il est assez évident que Xcode sait exactement ce qui a causé le crash (ou pourrait le savoir), mais ne montre toujours pas la ligne réelle. Y at-il une solution ou une solution de contournement pour cela?
Vous devez également vous assurer que des points d'arrêt sont définis pour toutes les exceptions. Cela provoquera l'arrêt de Xcode sur la ligne où l'exception se produit. Procédez comme suit [dans Xcode 4]:
Dans le navigateur de projet situé à gauche de Xcode, cliquez sur le navigateur de point d'arrêt (presque tout à fait à droite de la barre de boutons supérieure. L'icône ressemble à une grosse flèche droite).
Au bas du navigateur, cliquez sur le bouton "+".
Cliquez sur "Ajouter un point d'arrêt d'exception".
Un nouveau point d'arrêt sera créé. Il devrait être configuré au besoin, mais vous pouvez modifier son comportement.
Exécutez votre projet et reproduisez l'exception.
Vous avez également mentionné que vous aviez établi un lien avec certaines bibliothèques/structures tierces. Si l'exception se produit dans ces frameworks, vous allez avoir du mal à compiler le code et à ce que Xcode ne puisse pas vous montrer la ligne à l'origine de l'exception. Si tel est le cas et que vous êtes certain d’utiliser correctement les bibliothèques, vous devez alors signaler un rapport de bogue aux responsables de ces bibliothèques.
Suivez simplement les instructions de cette réponse à StackOverflow:
Fondamentalement, il vous suffit d'activer "Activer les zombies". Xcode devrait alors se rompre à la ligne ayant causé le problème.
(Il est absolument choquant que, même en 2017, Xcode l'ait toujours désactivée par défaut. Pourquoi voudriez-vous que {not} _ voie voir la ligne à l'origine du problème? Et "Enable Zombie Objects "?! Vraiment?! Les auteurs de Xcode croient-ils vraiment qu'il s'agit d'un nom utile, qui donnerait un sens quelconque aux nouveaux développeurs? Il est déprimant de constater à quel point la cote de Xcode est mauvaise, année après année, dans l'App Store. on écoute ...)
Editez le schéma actuel et activez NSZombieEnabled
, MallocStackLogging
et guard malloc
. Ensuite, lorsque votre application se bloque, tapez ceci dans la console gdb:
(gdb) info malloc-history 0x543216
Remplacez 0x543216
par l'adresse de l'objet qui a provoqué la NSInvalidArgumentException
. Elle devrait vous donner une trace de pile bien plus utile, montrant les lignes de votre code à l'origine du blocage.
J'ai vu ce comportement dans un code fortement optimisé; vérifier, ajuster le niveau d'optimisation de votre cible et ceux des bibliothèques tierces peut aider. (Paramètre de niveau d'optimisation LLVM 3.0)
Générez-vous des symboles de débogage?
J'ai écrit du code pour générer un crash d'index hors limite . La suite est l'exception levée.
2017-01-07 04:02:57.606 testABC[1694:52966] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e85cd4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010e2be21e objc_exception_throw + 48
2 CoreFoundation 0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111
3 testABC 0x000000010dce962d -[ViewController ComplexFunction] + 61
4 testABC 0x000000010dce95db -[ViewController thirdFunction] + 43
5 testABC 0x000000010dce959b -[ViewController secondFunction] + 43
6 testABC 0x000000010dce955b -[ViewController firstFinction] + 43
7 testABC 0x000000010dce96c2 -[ViewController viewDidAppear:] + 50
8 UIKit 0x000000010ee28a6c -[UIViewController _setViewAppearState:isAnimating:] + 945
9 UIKit 0x000000010ee2b7da __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 42
10 UIKit 0x000000010ee29ac4 -[UIViewController _executeAfterAppearanceBlock] + 86
11 UIKit 0x000000010ec8d77c _runAfterCACommitDeferredBlocks + 653
12 UIKit 0x000000010ec7a273 _cleanUpAfterCAFlushAndRunDeferredBlocks + 566
13 UIKit 0x000000010ec9d757 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke_2 + 194
14 CoreFoundation 0x000000010e8016ac __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
15 CoreFoundation 0x000000010e7e66f4 __CFRunLoopDoBlocks + 356
16 CoreFoundation 0x000000010e7e5e65 __CFRunLoopRun + 901
17 CoreFoundation 0x000000010e7e5884 CFRunLoopRunSpecific + 420
18 GraphicsServices 0x00000001126d9a6f GSEventRunModal + 161
19 UIKit 0x000000010ec80c68 UIApplicationMain + 159
20 testABC 0x000000010dce99df main + 111
21 libdyld.dylib 0x000000011174968d start + 1
22 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Si vous lisez attentivement le First Throw call stack
0 CoreFoundation 0x000000010e85cd4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010e2be21e objc_exception_throw + 48
0 and 1
sont les processus système après un crash.
2 CoreFoundation 0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111
2
est la ligne à l'origine de l'exception.
3 testABC 0x000000010dce962d -[ViewController ComplexFunction] + 61
3
vous indique le nom de la classe (ViewController
) et la fonction naem (ComplexFunction
) dans laquelle une exception a été levée.