Matt Wilding
Matt Wilding

Reputation: 20163

Can I get a stack trace for un-handled (Objective) C++ exceptions?

I'm developing an iOS application that has recently grown a large C++ base. C++ is not my forte, and I'm getting frustrated by exceptions. What I'm looking for is a way to get a stack track to the site of an (un-handled) exception throw. I'll say that the "un-handled" qualifier is optional; I would settle for breaking on any exception throw as a last resort, though un-handled exceptions are ideal.

What I currently get is useless. Assuming I don't have any appropriate exception handlers higher up the callstack, and I do something like

std::vector<int> my_vector;
my_vector.at(40) = 2; // Throws std::out_of_range

The app will break in main() and I'll get a log message saying "terminate called throwing an exception." Not helpful.

Putting generic try/catch blocks higher up the callstack doesn't help either, because the callstack is unwound during exception handling up to the point of the catch block, leaving me ignorant to actual origin of the exception. This also applies to providing my own terminate_handler. Asserts are more useful, but they require me to anticipate error conditions to some extent, which I cannot always do. I would still like the debugger to be able to step in even if an unexpected exception makes it past my pre-emptive assert()s.

What I want to avoid is having to wrap every call that might possibly throw an exception in a try/catch block just to get the stack trace to the error. At runtime, I'm really not interested in catching these exceptions. When they occur, it means there's a fatal flaw in the program execution, and there's no way it can continue normally. I just want to be notified so I can determine the cause and mend the issue so it won't happen again.


In Objective C, I can put a symbolic breakpoint on objc_exception_throw, and any time I screw something up I'll immediately break execution and be presented with a nice stack trace so I know where the issue is. Very helpful.

I realize this behavior is really only useful because of a philosophical difference in exception handling between the two languages. Objective C exceptions are intended only to signify unrecoverable errors. The task of routine error handling is accomplished via error return codes. This means that any Objective C exception is a great candidate for a breakpoint to the developer.

C++ seems to have a different use for Exceptions. They're used to handle both fatal errors and routine errors (at least in the 3rd party libs I'm using). This means I might not actually want to break on every exception that's thrown in C++, but I would still find the ability useful if I can't break only on un-handled exceptions.

Upvotes: 6

Views: 1985

Answers (3)

justin
justin

Reputation: 104698

You can quickly establish a break on all C++ throw conditions in Xcode:

  • cmd+6
  • "+" button -> Add Exception Breakpoint
    • C++ -> std::out_of_range
    • On Throw

Update

If you have a lot of them tho filter out, you may prefer to:

  • Create a Symbolic Breakpoint
  • Symbol = __cxa_throw (may vary by std library)
  • Action > Debugger Command = bt
  • Automatically continue after eval = On

The bt command logs the backtrace. Configured this way, it will automatically continue.

So, this will just log the backtrace of every thrown exception - when your program terminates due to an unhandled exception, the clues will be among the final logged backtraces (often the last, unless the library rethrows).

Upvotes: 5

Gilad Novik
Gilad Novik

Reputation: 4604

Check PLCrashReporter. We use it with our application (which relies heavily on C++) and it produces stack traces even for the C++ code.

The only problem you might have is when using assembly routines which were not written natively for iOS (Apple's compiler is using R7 to hold the stack frame for tracing back symbols which is not according to official ARM EBI)

Upvotes: 0

Mark
Mark

Reputation: 6128

In the app I get to debug with many c++ exceptions, I leave the "Catch C++ Exceptions on Throw" off until I get to the point in the app where it will throw the exception, then I turn that option on and usually the next exception that is thrown is what I'm looking for. This will break a few levels deeper than where the error is, but the stack is intact so you can figure out what is going on.

Upvotes: 1

Related Questions