How to Print Stack Trace for Caught Exceptions in C++ & Code Injection in C++

How can I print stack trace for caught exceptions in C++ & code injection in C++

Since you mentioned that you're happy with something that is GCC specific I've put together an example of a way you might do this. It's pure evil though, interposing on internals of the C++ support library. I'm not sure I'd want to use this in production code. Anyway:

#include <iostream>
#include <dlfcn.h>
#include <execinfo.h>
#include <typeinfo>
#include <string>
#include <memory>
#include <cxxabi.h>
#include <cstdlib>

namespace {
void * last_frames[20];
size_t last_size;
std::string exception_name;

std::string demangle(const char *name) {
int status;
std::unique_ptr<char,void(*)(void*)> realname(abi::__cxa_demangle(name, 0, 0, &status), &std::free);
return status ? "failed" : &*realname;
}
}

extern "C" {
void __cxa_throw(void *ex, void *info, void (*dest)(void *)) {
exception_name = demangle(reinterpret_cast<const std::type_info*>(info)->name());
last_size = backtrace(last_frames, sizeof last_frames/sizeof(void*));

static void (*const rethrow)(void*,void*,void(*)(void*)) __attribute__ ((noreturn)) = (void (*)(void*,void*,void(*)(void*)))dlsym(RTLD_NEXT, "__cxa_throw");
rethrow(ex,info,dest);
}
}

void foo() {
throw 0;
}

int main() {
try {
foo();
}
catch (...) {
std::cerr << "Caught a: " << exception_name << std::endl;
// print to stderr
backtrace_symbols_fd(last_frames, last_size, 2);
}
}

We basically steal calls to the internal implementation function that GCC uses for dispatching thrown exceptions. At that point we take a stack trace and save it in a global variable. Then when we come across that exception later on in our try/catch we can work with the stacktrace to print/save or whatever it is you want to do. We use dlsym() to find the real version of __cxa_throw.

My example throws an int to prove that you can do this with literally any type, not just your own user defined exceptions.

It uses the type_info to get the name of the type that was thrown and then demangles it.

You could encapsulate the global variables that store the stacktrace a bit better if you wanted to.

I compiled and tested this with:

g++ -Wall -Wextra test.cc -g -O0 -rdynamic -ldl

Which gave the following when run:


./a.out
Caught a: int
./a.out(__cxa_throw+0x74)[0x80499be]
./a.out(main+0x0)[0x8049a61]
./a.out(main+0x10)[0x8049a71]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb75c2ca6]
./a.out[0x80497e1]

Please don't take this as an example of good advice though - it's an example of what you can do with a little bit of trickery and poking around at the internals!

C++ display stack trace on exception

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.

c++ stack trace from unhandled exception?

Edited Answer:

You can use std::set_terminate

#include <cstdlib>
#include <iostream>
#include <stdexcept>

#include <execinfo.h>

void
handler()
{
void *trace_elems[20];
int trace_elem_count(backtrace( trace_elems, 20 ));
char **stack_syms(backtrace_symbols( trace_elems, trace_elem_count ));
for ( int i = 0 ; i < trace_elem_count ; ++i )
{
std::cout << stack_syms[i] << "\n";
}
free( stack_syms );

exit(1);
}

int foo()
{
throw std::runtime_error( "hello" );
}

void bar()
{
foo();
}

void baz()
{
bar();
}

int
main()
{
std::set_terminate( handler );
baz();
}

giving this output:

samm@macmini ~> ./a.out 
./a.out [0x10000d20]
/usr/lib/libstdc++.so.6 [0xf9bb8c8]
/usr/lib/libstdc++.so.6 [0xf9bb90c]
/usr/lib/libstdc++.so.6 [0xf9bbaa0]
./a.out [0x10000c18]
./a.out [0x10000c70]
./a.out [0x10000ca0]
./a.out [0x10000cdc]
/lib/libc.so.6 [0xfe4dd80]
/lib/libc.so.6 [0xfe4dfc0]
samjmill@bgqfen4 ~>

assuming you have debug symbols in your binary, you can then use addr2line to construct a prettier stack trace postmortem

samm@macmini ~> addr2line 0x10000c18
/home/samm/foo.cc:23
samm@macmini ~>

original answer is below


I've done this in the past using boost::error_info to inject the stack trace using backtrace from execinfo.h into an exception that is thrown.

typedef boost::error_info<struct tag_stack_str,std::string> stack_info;

Then when catching the exceptions, you can do

} catch ( const std::exception& e ) {                                                                                                            
if ( std::string const *stack boost::get_error_info<stack_error_info>(e) ) {
std::cout << stack << std::endl;
}
}

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

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).

Portable C++ Stack Trace on Exception

I think this is a really bad idea.

Portability is a very worthy goal, but not when it results in a solution that is intrusive, performance-sapping, and an inferior implementation.

Every platform (Windows/Linux/PS2/iPhone/etc) I've worked on has offered a way to walk the stack when an exception occurs and match addresses to function names. Yes, none of these are portable but the reporting framework can be and it usually takes less than a day or two to write a platform-specific version of stack walking code.

Not only is this less time than it'd take creating/maintaining a cross-platform solution, but the results are far better;

  • No need to modify functions
  • Traps crashes in standard or third party libraries
  • No need for a try/catch in every function (slow and memory intensive)

How to make C++ give detailed exception information just like python does?

You could use the __FILE__ and __LINE__ definitions in your exception message.

For example:

#include <stdexcept>

class Error : public std::runtime_error
{
public:
Error (const std::string &message)
: std::runtime_error(message)
{}

};

int value()
{
std::stringstream ss;
ss << "Issues at " << __FILE__ << " on line " << __LINE__;
throw Error(ss.str());
}

In this example, I made Error inherit from std::runtime_error (which has a constructor to allow you to pass a message as a string)...

Additionally, take a look at this SO question: Global Exception Handling - note the answer about using the set_terminate function. This will allow you to install a global handler that ensures the message is printed as you want. Here's some info on set_terminate().

Python gives a stack trace for an uncaught exception. The answer I've provided only tells you the file and line number. If you need a stack trace, several commenters have referenced some other SO questions that give advice on how to do this in C++. Beware of non-standard solutions to this issue, however.



Related Topics



Leave a reply



Submit