Getting the backtrace from the catch block
Asked Answered
C

3

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?

Consequential answered 26/11, 2010 at 9:18 Comment(2)
You might want to take a look through this post. It might get you somewhere near to where you want to be.Paperback
The problem with std::set_terminate is that the program will still terminate when the callback is called.Subscribe
K
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.

Karalee answered 26/11, 2010 at 9:29 Comment(2)
Yes, exactly. Which brings us to "how do I do something when exception is thrown" - https://mcmap.net/q/824510/-how-can-some-code-be-run-each-time-an-exception-is-thrown-in-a-visual-c-program/57428Repository
Len Holgate mentioned Debug API to catch exception exactly when it's being thrown. Seems complicated, but doable.Karalee
C
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!

Cid answered 26/11, 2010 at 9:31 Comment(4)
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 :(Subscribe
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!Textile
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.Subscribe
No problem. Hope you find what you're looking for.Textile
K
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.

Karalee answered 26/11, 2010 at 9:29 Comment(2)
Yes, exactly. Which brings us to "how do I do something when exception is thrown" - https://mcmap.net/q/824510/-how-can-some-code-be-run-each-time-an-exception-is-thrown-in-a-visual-c-program/57428Repository
Len Holgate mentioned Debug API to catch exception exactly when it's being thrown. Seems complicated, but doable.Karalee
I
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.

Ironic answered 26/11, 2010 at 9:54 Comment(4)
But I am not linux, therefore no visual studio here ;)Subscribe
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_rangeSubscribe
@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?Ironic
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.Subscribe

© 2022 - 2024 — McMap. All rights reserved.