ChatGPT解决这个技术问题 Extra ChatGPT

如何将堆栈跟踪打印到控制台/登录 Cocoa?

我想在某些时间点记录调用跟踪,例如失败的断言或未捕获的异常。


P
Paulo Mattos

此代码适用于任何线程:

NSLog(@"%@", NSThread.callStackSymbols);

返回一个包含调用堆栈符号的数组。每个元素都是一个 NSString 对象,其值的格式由 backtrace_symbols() 函数确定。


Mac OS X 10.6 中的新功能,最初提出此问题时不存在。对于 Pre-Snow-Leopard,使用 backtracebacktrace_symbols 函数;请参阅 backtrace(3) 联机帮助页。
仅适用于 iOS 4.0 及更高版本。
谢谢!有没有办法让它只打印堆栈跟踪,比如说,向下 6 级而不是一路?
9000,直接使用backtrace/backtrace_symbols
@sudo 这是一个数组,所以只需定义范围 [NSThread.callStackSymbols subarrayWithRange:NSMakeRange(0, MIN(6, NSThread.callStackSymbols.count))];
C
Cœur

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;
    }
}

Gah... Apple 至少在开发应用程序时应该将此作为标准。一堆内存地址是......过时的
我把你的改进放在我的回答中;我在 ARC 之前做过这个。谢谢。
并非适用于所有情况。如果您想捕获所有未捕获的异常,这是一种更好的方法:codereview.stackexchange.com/questions/56162/…(该问题中的代码有点过于复杂,但它不仅仅是简单地记录调用堆栈符号。)
如果您也想要实际的异常,可以添加 NSLog(@"[Error] - %@ %@", exception.name, exception.reason);
C
Cœur

Cocoa 已经在控制台中记录了未捕获异常的堆栈跟踪,尽管它们只是原始内存地址。如果您想要控制台中的符号信息,Apple 提供了一些 sample code

如果您想在代码中的任意点生成堆栈跟踪(并且您在 Leopard 上),请参阅 backtrace 手册页。在 Leopard 之前,您实际上必须挖掘调用堆栈本身。


显然在 iOS 4 中可用,但在 3.2 中不可用。这是我使用的,从回溯手册页无耻地复制:#include ... void* callstack[128]; int i,帧 = 回溯(调用堆栈,128); char** strs = backtrace_symbols(callstack, frames); for (i = 0; i < 帧; ++i) { printf("%s\n", strs[i]); } 自由(strs);
在 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 替换。
C
Cœur

This 几乎告诉您该怎么做。

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

#import <ExceptionHandling/NSExceptionHandler.h>

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

请注意,尽管这仅适用于已注册的异常处理程序(例如,在 @catch 块中)
B
Ben Gottlieb

对于异常,您可以使用异常的 userInfo 字典的 NSStackTraceKey 成员来执行此操作。请参阅 Apple 网站上的 Controlling a Program's Response to Exceptions


如何在 Swift 中使用?
D
Dipak

以这种方式快速打印:

print("stack trace:\(Thread.callStackSymbols)")

m
miragessee

如果你想得到它作为 NSString。

[NSThread  callStackSymbols].description