Как вы распечатываете трассировку стека в консоли / журнале в Какао?


293

Я хотел бы регистрировать трассировку вызовов во время определенных моментов, таких как ошибочные утверждения или неперехваченные исключения.

Ответы:


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

Этот код работает в любом потоке.


14
Новое в Mac OS X 10.6, которого не было, когда изначально задавался этот вопрос. Для предварительной снежно-Leopard, использовать backtraceи backtrace_symbolsфункцию; см. справочную страницу backtrace (3).
Питер Хоси

6
Только на iOS 4.0 и выше.
Данра

Спасибо! Есть ли способ заставить это только печатать трассировку стека, скажем, на 6 уровней вниз вместо всего?
Судо

9000, используйте backtrace/backtrace_symbolsнапрямую
dymv

34

Ответ n13 не совсем сработал - я немного изменил его, чтобы придумать

#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 должна сделать это стандартом, по крайней мере, при разработке приложения. Куча адресов памяти ... архаична
Расс

Я положил ваши улучшения в моем ответе; Я сделал это до ARC. Спасибо.
13

1
Это не работает во всех ситуациях. Это лучший подход, если вы хотите перехватить все неперехваченные исключения: codereview.stackexchange.com/questions/56162/… (код в этом вопросе немного сложнее, но он также делает больше, чем просто записывает символы стека вызовов).
nhgrif

Вы можете добавить, NSLog(@"[Error] - %@ %@", exception.name, exception.reason);если вы хотите, чтобы фактическое исключение тоже
Corentin S.

9

Какао уже регистрирует трассировку стека на необработанных исключениях в консоли, хотя они являются просто необработанными адресами памяти. Если вам нужна символическая информация в консоли, то есть пример кода от Apple.

Если вы хотите сгенерировать трассировку стека в произвольной точке вашего кода (и вы находитесь на Leopard), обратитесь к странице справки backtrace. До Leopard вам действительно приходилось копаться в самом стеке вызовов.


6
По-видимому, доступно в iOS 4, но не 3.2. Вот что я использовал, беспардонно скопированный со страницы руководства backtrace: #include <execinfo.h> ... void * callstack [128]; int i, frames = backtrace (callstack, 128); char ** strs = backtrace_symbols (callstack, frames); for (i = 0; i <frames; ++ i) {printf ("% s \ n", strs [i]); } бесплатно (стрс);
Mharper

При вызове в HandleException он записывает трассировку самой функции-обработчика, в то время как [NSException callStackSymbols] показывает стек места, где возникло исключение. Но если вы замените «backtrace (...)» на: «NSArray arr = [ex callStackReturnAddresses]; int frames = arr.count; for (i = 0; i <frames; ++ i) callstack [i] = ( void) [((NSNumber *) [arr objectAtIndex: i]) intValue]; " вы получите текущую трассировку стека исключений. Вот как работает [NSException callStackSymbols], я полагаю: трассировки, которые они возвращают, равны и в обоих вызовах приложения заменяются _mh_execute_header в релизе.
Tertium

6

Это в значительной степени говорит вам, что делать.

По сути, вам нужно настроить обработку исключений приложений для регистрации, что-то вроде:

#import <ExceptionHandling/NSExceptionHandler.h>

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

1
Обратите внимание, что это будет работать только в зарегистрированном обработчике исключений (например, не в блоке @catch)
Барри Уарк


1

Быстрая печать следующим образом:

print("stack trace:\(Thread.callStackSymbols)")
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.