C++ display stack trace on exception

279,542

Solution 1

It depends which platform.

On GCC it's pretty trivial, see this post for more details.

On MSVC then you can use the StackWalker library that handles all of the underlying API calls needed for Windows.

You'll have to figure out the best way to integrate this functionality into your app, but the amount of code you need to write should be minimal.

Solution 2

Andrew Grant's answer does not help getting a stack trace of the throwing function, at least not with GCC, because a throw statement does not save the current stack trace on its own, and the catch handler won't have access to the stack trace at that point any more.

The only way - using GCC - to solve this is to make sure to generate a stack trace at the point of the throw instruction, and save that with the exception object.

This method requires, of course, that every code that throws an exception uses that particular Exception class.

Update 11 July 2017: For some helpful code, take a look at cahit beyaz's answer, which points to http://stacktrace.sourceforge.net - I haven't used it yet but it looks promising.

Solution 3

If you are using Boost 1.65 or higher, you can use boost::stacktrace:

#include <boost/stacktrace.hpp>

// ... somewhere inside the bar(int) function that is called recursively:
std::cout << boost::stacktrace::stacktrace();

Solution 4

I would like to add a standard library option (i.e. cross-platform) how to generate exception backtraces, which has become available with C++11:

Use std::nested_exception and std::throw_with_nested

This won't give you a stack unwind, but in my opinion the next best thing. It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.

Since you can do this with any derived exception class, you can add a lot of information to such a backtrace! You may also take a look at my MWE on GitHub, where a backtrace would look something like this:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"

Solution 5

Unix: backtrace

Mac: backtrace

Windows: CaptureBackTrace

Share:
279,542

Related videos on Youtube

rlbond
Author by

rlbond

I like C++. I also like Python.

Updated on December 01, 2021

Comments

  • rlbond
    rlbond over 2 years

    I want to have a way to report the stack trace to the user if an exception is thrown. What is the best way to do this? Does it take huge amounts of extra code?

    To answer questions:

    I'd like it to be portable if possible. I want information to pop up, so the user can copy the stack trace and email it to me if an error comes up.

  • Shep
    Shep about 10 years
    the post you link to mostly points to generating a trace from a segfault, but the asker specifically mentions exceptions, which are quite a different beast.
  • damianostre
    damianostre over 9 years
    I agree with @Shep - this answer does not really help with getting a stack trace of the throwing code on GCC. See my answer for a possible solution.
  • warran
    warran almost 9 years
    Unfortunately the link is dead. Could you provide some other?
  • damianostre
    damianostre almost 9 years
    And archive.org doesn't know it, either. Damn. Well, the procedure should be clear: throw a custom class' object that records the stack trace at the time of the throw.
  • xaxxon
    xaxxon almost 8 years
    libunwind 1.1 doesn't build on os x.
  • Keyur Padalia
    Keyur Padalia over 6 years
    On its home page, I see throw stack_runtime_error. Am I correct in deducing that this lib only works for exceptions derived from that class, and not for std::exception or exceptions from third-party libraries?
  • Keyur Padalia
    Keyur Padalia over 6 years
    On the home page of StackTrace, I see throw stack_runtime_error. Am I correct in deducing that this lib only works for exceptions derived from that class, and not for std::exception or exceptions from third-party libraries?
  • Code Abominator
    Code Abominator over 6 years
    So sadly the answer is "No, you cannot get a stack trace from a C++ exception", the only option is to throw your own class which generates a stack trace when it's constructed. If you're stuck using things like, say, any part of the C++ std:: library, you're out of luck. Sorry, sucks to be you.
  • zhaorufei
    zhaorufei over 6 years
    I checked this project at 2017.12.24, source and download both not accessiable.
  • Boris
    Boris over 6 years
    I just checked code.google.com/archive/p/exception-diagnostic/source/defaul‌​t/… and the source is downloadable. Can you try one more time?
  • moodboom
    moodboom over 6 years
    The boost docs explain not only capturing a stack trace, but how to do it for exceptions and asserts. Great stuff.
  • fjardon
    fjardon about 6 years
    This answer is misleading. The link points to an answer specific to Linux not gcc.
  • Clearer
    Clearer almost 6 years
    This is probably a lot better, if you're willing to do the extra work, than the usual dumb stack trace.
  • Gimhani
    Gimhani over 5 years
    Does this stacktrace() prints source file and line numbers as given in the GettingStarted guide ?
  • ingomueller.net
    ingomueller.net over 4 years
    You can override the throw mechanism of libstdc++ (used by GCC and potentially Clang) as explained in this answer.
  • Andrew
    Andrew over 3 years
    "Then sprinkle the STACK~ macros over your code... Just place it at the start of each function you want stack-traced." Uh yeah, no.
  • Andrew
    Andrew over 3 years
    Documentation link dead.
  • Boris
    Boris over 3 years
    Just checked and both links above opens. Could you describe the problem?
  • Martin
    Martin over 2 years
    It's been a while since I've felt horrified of how C++ can butcher such a simple concept. Thanks for the reminder.