Xcode 4.2 debug ne symbolise pas l'appel de pile

J'ai un problème avec le débogage Xcode 4.2 dans un simulateur/périphérique iOS 5. Le code suivant se bloque, comme prévu:

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

Dans iOS 4, j'obtiens une trace de pile utile de nombres hexadécimaux. Mais dans iOS 5, Il me donne juste:

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

Merci.

137
demandé sur WiseOldDuck 2011-10-21 00:07:23

9 réponses

Rien que j'ai essayé ne corrigerait cela (essayé les deux compilateurs, les deux débogueurs, etc.) Après la mise à niveau de XCode pour la mise à jour iOS 5, aucune trace de pile ne semblait fonctionner.

Cependant, j'ai trouvé un contournement efficace-créer mon propre gestionnaire d'exceptions (ce qui est également utile pour d'autres raisons). Tout d'abord, créez une fonction qui va gérer l'erreur et la sortir sur la console (ainsi que tout ce que vous voulez faire avec elle):

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

Ensuite, ajoutez le gestionnaire d'exceptions à votre application délégué:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

C'est ça!

Si cela ne fonctionne pas, alors il n'y a que deux raisons possibles :

  1. quelque chose écrase votre appel NSSetUncaughtExceptionHandler (il ne peut y avoir qu'un seul gestionnaire pour l'ensemble de votre application). Par exemple, certaines bibliothèques tierces définissent leur propre uncaughtExceptionHandler. Alors, essayez de le définir à la fin de votre fonction didFinishLaunchingWithOptions (ou désactivez sélectivement les bibliothèques tierces). Ou mieux encore, définissez un point de rupture symbolique sur NSSetUncaughtExceptionHandler pour voir rapidement qui appelle il. Ce que vous pouvez faire est de modifier votre actuelle plutôt que d'en ajouter un autre.
  2. Vous ne rencontrez pas réellement d'exception (par exemple, EXC_BAD_ACCESS est Pas une exception; crédit aux commentaires de @ Erik B, ci-dessous)
252
répondu Zane Claes 2013-05-28 13:45:30

Il existe une option utile pour ajouter un point D'arrêt D'Exception (en utilisant le + en bas du navigateur de point D'arrêt). Cela cassera sur n'importe quelle Exception (ou vous pouvez définir des conditions). Je ne sais pas si ce choix est nouveau dans 4.2 ou si Je ne l'ai finalement remarqué qu'en essayant de contourner le problème des symboles manquants.

Une fois que vous avez atteint ce point d'arrêt, vous pouvez utiliser le navigateur de débogage pour naviguer dans la pile d'appels, examiner les variables, etc. comme d'habitude.

Si vous voulez une pile d'appels symbolisée approprié pour copier / coller ou similaire, gdb backtrace fonctionnera bien à partir de là:

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(etc)

108
répondu WiseOldDuck 2011-11-22 16:41:02

Il est une nouvelle fonctionnalité sur le débogueur. Vous pouvez définir un point d'arrêt chaque fois qu'une exception est levée et arrêter l'exécution juste là, comme cela se produisait sur 4.0.

Sur le "navigateur de point D'arrêt", ajoutez un" point D'arrêt D'Exception "et appuyez simplement sur" Terminé " dans la fenêtre contextuelle options.

C'est tout!

PS: dans certains cas, il serait préférable de ne casser que pour les exceptions Objective-C.

45
répondu Pedro 2011-11-07 17:23:39

Voici une solution de plus, pas aussi élégante que la précédente, mais si vous n'avez pas ajouté de points d'arrêt ou de gestionnaires d'exception, ce ne peut être qu'une solution.
Lorsque l'application se bloque et que vous obtenez votre première pile d'appels (en nombres hexadécimaux), tapez dans la console Xcode info line *hex (n'oubliez pas le spécificateur star et 0x hexadécimal), par exemple:

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

Si vous utilisez lldb, vous pouvez taper image lookup -a hex (sans les étoiles dans cette situation), et vous obtenez le même résultat.

Avec cette méthode, vous pouvez traverser du haut de la pile throw (il y aura environ 5-7 propagateurs d'exception système) à votre fonction qui a provoqué un crash, et déterminer le fichier exact et la ligne de code.

Aussi, pour un effet similaire, vous pouvez utiliser l'utilitaire atos dans le terminal, il suffit de taper:

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

Et vous obtenez une trace de pile symbolisée (au moins pour les fonctions, vous avez des symboles de débogage). Cette méthode est plus préférable, car vous n'avez pas pour chaque appel d'adresse info line, Il suffit de copier les adresses de la sortie de la console et collez-les dans le terminal.

21
répondu goodfella 2012-03-14 21:41:48

Vous pouvez ajouter un point D'arrêt Exception (en utilisant le + en bas du navigateur de point D'arrêt) et Ajouter l'action bt pour cela (cliquez sur le bouton Ajouter une Action, sélectionnez la commande débogueur, entrez " bt " dans le champ de texte). Cela affichera la trace de la pile dès qu'une exception est levée.

9
répondu MonsieurDart 2012-10-26 11:47:57

C'est un problème commun, ne pas obtenir de traces de pile dans 4.2. Vous pouvez essayer d'échanger entre LLDB et GDB pour voir si vous obtenez de meilleurs résultats.

Déposez un rapport de bogue ici.

Http://developer.apple.com/bugreporter/

Modifier:

Je crois que si vous revenez à LLVM GCC 4.2, vous ne verrez pas cela se produire. Vous risquez de perdre les fonctionnalités dont vous avez besoin.

6
répondu logancautrell 2011-10-20 20:10:34

Utilisez ce code dans votre fonction principale:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int retVal;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException *exception) {
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    }
    @finally {
        [pool release];
    }
    return retVal;
}
6
répondu wilson lin 2012-02-13 23:11:58

À L'invite de console de débogage de Xcode, tapez:

image lookup -a 0x1234

Et il vous montrera quelque chose comme:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
6
répondu Matt Connolly 2013-10-31 00:44:07

Retourner 'compiler pour le pouce' (configuration de débogage) a fonctionné pour moi.

1
répondu Bradweiser86 2012-01-25 21:42:01