如何在Cocoa中将堆栈跟踪打印到控制台/日志?


293

我想在某些时候记录呼叫跟踪,例如失败的断言或未捕获的异常。

Answers:


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

此代码可在任何线程上运行。


14
Mac OS X 10.6中的新增功能,最初提出此问题时不存在。对于雪豹之前的版本,请使用backtracebacktrace_symbols功能。请参见backtrace(3)联机帮助页。
彼得·霍西

6
仅在iOS 4.0及更高版本上。
丹拉2011年

谢谢!有没有办法使它仅打印堆栈跟踪,例如向下打印6层而不是一直打印?
sudo 2014年

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应该至少在开发应用程序时将此标准作为标准。一堆内存地址是...过时的
Russ 2013年

我把你的改进放在我的答案中;我在ARC之前就这样做了。谢谢。
n13

1
并不适用于所有情况。如果您想捕获所有未捕获的异常,这是一种更好的方法:codereview.stackexchange.com/questions/56162/…(该问题中的代码有些复杂,但它不仅记录了调用堆栈符号,还提供了更多功能。)
nhgrif 2014年

您也可以添加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,框架= backtrace(callstack,128); char ** strs = backtrace_symbols(调用堆栈,帧); 对于(i = 0; i <frame; ++ i){printf(“%s \ n”,strs [i]); } free(strs);
mharper

在HandleException中被调用时,它会写回处理程序函数本身的踪迹,而[NSException callStackSymbols]显示了引发异常的地方的堆栈。但是,如果将“ backtrace(...)”替换为:“ NSArray arr = [ex callStackReturnAddresses]; int frame = arr.count; for(i = 0; i <frames; ++ i)callstack [i] =( void)[(((NSNumber *)[arr objectAtIndex:i])intValue];“ 您将获得当前的异常堆栈跟踪。我想这就是[NSException callStackSymbols]的工作方式:它们返回的跟踪是相等的,并且在两个应用程序调用中,在发行版中都被_mh_execute_header替换。
Tertium 2012年

6

几乎可以告诉您该怎么做。

本质上,您需要设置应用程序异常处理以进行记录,例如:

#import <ExceptionHandling/NSExceptionHandler.h>

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

1
请注意,尽管这仅在注册的异常处理程序中有效(例如,在@catch块中无效)
Barry Wark


1

以这种方式快速打印:

print("stack trace:\(Thread.callStackSymbols)")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.