15

I am using backtrace to get the information from where the exception is thrown. In the constructor of my exception, I am storing the backtrace in a std::string, and in the catch block for exceptions of this type, I am printing this backtrace.

But I was wondering, is it possible to somehow get the same backtrace in the catch block for other exception types?

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • You might want to take a look through [this post](http://stackoverflow.com/questions/3355683/c-stack-trace-from-unhandled-exception "c-stack-trace-from-unhandled-exception"). It might get you somewhere near to where you want to be. – Component 10 Nov 26 '10 at 09:29
  • The problem with std::set_terminate is that the program will still terminate when the callback is called. – BЈовић Nov 26 '10 at 13:58

3 Answers3

10

You might be interested in a Boost library under development: Portable Backtrace. Example:

#include <boost/backtrace.hpp>
#include <iostream>

int foo()
{
    throw boost::runtime_error("My Error");
    return 10;
}

int bar()
{
    return foo()+20;
}


int main()
{
    try {
        std::cout << bar() << std::endl;
    }
    catch(std::exception const &e)
    {
        std::cerr << e.what() << std::endl;
        std::cerr << boost::trace(e);
    }
}

Prints:

My Error
0x403fe1: boost::stack_trace::trace(void**, int) + 0x1b in ./test_backtrace
0x405451: boost::backtrace::backtrace(unsigned long) + 0x65 in ./test_backtrace
0x4054d2: boost::runtime_error::runtime_error(std::string const&) + 0x32 in ./test_backtrace
0x40417e: foo() + 0x44 in ./test_backtrace
0x40425c: bar() + 0x9 in ./test_backtrace
0x404271: main + 0x10 in ./test_backtrace
0x7fd612ecd1a6: __libc_start_main + 0xe6 in /lib/libc.so.6
0x403b39: __gxx_personality_v0 + 0x99 in ./test_backtrace

Hope this helps!

Daniel Lidström
  • 9,930
  • 1
  • 27
  • 35
  • Yes, that is exactly what I need, but as far as I can see, it is still in the boost release, and at the moment I am locked into boost 1.34.1 :( – BЈовић Nov 26 '10 at 10:07
  • 2
    Perhaps you can download it separately and use it standalone. Then when/if it makes it into an official Boost you might be able to switch/upgrade. Good luck! – Daniel Lidström Nov 26 '10 at 10:17
  • 1
    Sorry, but I realized that this doesn't answer my question. For this, you have to throw boost exceptions, but the backtrace is not printed if another exception type is caught. – BЈовић Nov 26 '10 at 13:51
  • No problem. Hope you find what you're looking for. – Daniel Lidström Nov 26 '10 at 13:53
8

I don't think so. When executons stops in catch block the stack is unwound, and all that has happened before is not in stack anymore.

Dialecticus
  • 16,400
  • 7
  • 43
  • 103
  • Yes, exactly. Which brings us to "how do I do something when exception is *thrown*" - http://stackoverflow.com/q/4223390/57428 – sharptooth Nov 26 '10 at 10:53
  • Len Holgate mentioned Debug API to catch exception exactly when it's being thrown. Seems complicated, but doable. – Dialecticus Nov 26 '10 at 10:57
1

Do the classes in question share a common base you can edit?

Otherwise, I provided a wonderful but terribly underappreciated answer at How can some code be run each time an exception is thrown in a Visual C++ program? ;-P Some others opined too.

Community
  • 1
  • 1
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • But I am not linux, therefore no visual studio here ;) – BЈовић Nov 26 '10 at 10:05
  • Yes, the exception classes I am throwing have a common base, and I can get the backtrace for those. The problem is how to get the backtrace from other exception types? For example std::out_of_range – BЈовић Nov 26 '10 at 10:06
  • @VJo: my dirty hack wasn't Visual C++ specific (in fact, I tested it only in GCC) - but it's not suitable for serious production usage either. For std::out_of_range, it's a hassle - guess it depends how valuable it is to you, but you could explore changing std::exception itself, using debugger techniques. Are you dealing with std::out_of_range et al thrown from 3rd party libraries (if so, do you even have sources), or just in your own code? Is there too much source to change the throw statements? – Tony Delroy Nov 26 '10 at 10:27
  • I can not use that, since it works only if the exception if thrown from the same compilation unit (cpp file). Once the function throwing an exception is in another file, it will not work. – BЈовић Nov 26 '10 at 11:07