Come si stampa una traccia dello stack sulla console / accesso in Cocoa?


293

Vorrei registrare la traccia della chiamata durante determinati punti, come asserzioni non riuscite o eccezioni non rilevate.

Risposte:


544
 NSLog(@"%@",[NSThread callStackSymbols]);

Questo codice funziona su qualsiasi thread.


14
Novità in Mac OS X 10.6, che non esisteva quando questa domanda è stata inizialmente posta. Per Pre-Snow-Leopard, utilizzare le funzioni backtracee backtrace_symbols; vedere la manpage backtrace (3).
Peter Hosey,

6
Solo su iOS 4.0 e versioni successive.
Danra,

Grazie! C'è un modo per farlo stampare solo la traccia dello stack, diciamo, 6 livelli in basso invece che completamente?
sudo,

9000, utilizzare backtrace/backtrace_symbolsdirettamente
dymv,

34

La risposta di n13 non ha funzionato del tutto - l'ho modificata leggermente per trovare questo

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        int retval;
        @try{
            retval = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
        @catch (NSException *exception)
        {
            NSLog(@"Gosh!!! %@", [exception callStackSymbols]);
            @throw;
        }
        return retval;
    }
}

4
Gah ... Apple dovrebbe renderlo uno standard almeno durante lo sviluppo di un'applicazione. Un mucchio di indirizzi di memoria è ... arcaico
Russ,

Ho inserito i tuoi miglioramenti nella mia risposta; L'ho fatto prima di ARC. Grazie.
13

1
Questo non funziona in tutte le situazioni. Questo è un approccio migliore se vuoi catturare tutte le eccezioni non rilevate : codereview.stackexchange.com/questions/56162/… (Il codice in quella domanda è un po 'troppo complicato, ma fa anche molto di più che semplicemente registrare i simboli dello stack di chiamate.)
nhgrif,

NSLog(@"[Error] - %@ %@", exception.name, exception.reason);Se lo desideri, puoi aggiungere anche l'eccezione effettiva
Corentin S.

9

Cocoa registra già la traccia dello stack su eccezioni non rilevate sulla console sebbene siano solo indirizzi di memoria non elaborati. Se vuoi informazioni simboliche nella console, c'è un codice di esempio di Apple.

Se vuoi generare una traccia dello stack in un punto arbitrario nel tuo codice (e sei su Leopard), vedi la pagina man backtrace. Prima di Leopard, dovevi effettivamente scavare nello stack di chiamate stesso.


6
Apparentemente disponibile in iOS 4 ma non 3.2. Ecco cosa ho usato, copiato senza vergogna dalla pagina man backtrace: #include <execinfo.h> ... void * callstack [128]; int i, frames = backtrace (callstack, 128); char ** strs = backtrace_symbols (callstack, frames); per (i = 0; i <frame; ++ i) {printf ("% s \ n", strs [i]); } gratuito (strs);
mharper,

Essendo chiamato in HandleException, riscrive la traccia della funzione del gestore stesso, mentre [NSException callStackSymbols] mostra lo stack del luogo in cui è stata sollevata l'eccezione. Ma se si sostituisce "backtrace (...)" con: "NSArray arr = [ex callStackReturnAddresses]; int frames = arr.count; for (i = 0; i <frames; ++ i) callstack [i] = ( void) [((NSNumber *) [arr objectAtIndex: i]) intValue]; " otterrai l'attuale traccia dello stack delle eccezioni. Ecco come funziona [NSException callStackSymbols], suppongo: le tracce che restituiscono sono uguali e in entrambe le chiamate delle app vengono sostituite da _mh_execute_header in versione.
Tertium,

6

Questo ti dice praticamente cosa fare.

Fondamentalmente è necessario impostare la gestione delle eccezioni delle applicazioni per accedere, qualcosa del tipo:

#import <ExceptionHandling/NSExceptionHandler.h>

[[NSExceptionHandler defaultExceptionHandler] 
                  setExceptionHandlingMask: NSLogUncaughtExceptionMask | 
                                            NSLogUncaughtSystemExceptionMask | 
                                            NSLogUncaughtRuntimeErrorMask]

1
Si noti, tuttavia, che funzionerà solo all'interno di un gestore di eccezioni registrato (non, ad esempio, in un blocco @catch)
Barry Wark,


1

Stampa rapida in questo modo:

print("stack trace:\(Thread.callStackSymbols)")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.