ChatGPT解决这个技术问题 Extra ChatGPT

How do you print out a stack trace to the console/log in Cocoa?

I'd like to log the call trace during certain points, like failed assertions, or uncaught exceptions.


P
Paulo Mattos

This code works on any thread:

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

Returns an array containing the call stack symbols. Each element is an NSString object with a value in a format determined by the backtrace_symbols() function.


New in Mac OS X 10.6, which didn't exist when this question was originally asked. For pre-Snow-Leopard, use the backtrace and backtrace_symbols functions; see the backtrace(3) manpage.
Only on iOS 4.0 and above.
Thanks! Is there a way to make this only print the stack trace, say, 6 levels down instead of all the way?
9000, use backtrace/backtrace_symbols directly
@sudo It's an array so just define range [NSThread.callStackSymbols subarrayWithRange:NSMakeRange(0, MIN(6, NSThread.callStackSymbols.count))];
C
Cœur

n13's answer didn't quite work - I modified it slightly to come up with this

#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 should make this a standard at least while developing an application. A bunch of memory addresses is... archaic
I put your improvements in my answer; I did this before ARC. Thanks.
This doesn't work in all situations. This is a better approach if you want to catch all uncaught exceptions: codereview.stackexchange.com/questions/56162/… (The code in that question is a little overcomplicated, but it also does more than simply log the call stack symbols.)
You can add NSLog(@"[Error] - %@ %@", exception.name, exception.reason); if you want the actual exception too
C
Cœur

Cocoa already logs the stack trace on uncaught exceptions to the console although they're just raw memory addresses. If you want symbolic information in the console there's some sample code from Apple.

If you want to generate a stack trace at an arbitrary point in your code (and you're on Leopard), see the backtrace man page. Before Leopard, you actually had to dig through the call stack itself.


Apparently available in iOS 4 but not 3.2. Here's what I used, shamelessly copied from the backtrace man page: #include ... 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]); } free(strs);
Being called in HandleException it writes back trace of handler function itself, while [NSException callStackSymbols] shows stack of the place where exception has raised. But if you replace "backtrace(...)" with: "NSArray arr = [ex callStackReturnAddresses]; int frames = arr.count; for (i = 0; i < frames; ++i) callstack[i] = (void) [((NSNumber *) [arr objectAtIndex:i]) intValue];" you will get current exception stack trace. This is how [NSException callStackSymbols] works, I suppose: traces they return are equal and in both app calls are replaced by _mh_execute_header in release.
C
Cœur

This pretty much tells you what to do.

Essentially you need to set up the applications exception handling to log, something like:

#import <ExceptionHandling/NSExceptionHandler.h>

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

Note, though that this will only work within a registered exception handler (not, e.g., in a @catch block)
B
Ben Gottlieb

For exceptions, you can use the NSStackTraceKey member of the exception's userInfo dictionary to do this. See Controlling a Program's Response to Exceptions on Apple's website.


How to use in Swift?
D
Dipak

In swift print this way:

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

m
miragessee

If you want to get it as NSString.

[NSThread  callStackSymbols].description