C++ Stack Trace from Unhandled Exception

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;
}
}

Get stack trace from uncaught exception?

We implemented MiniDumps for unhandled exceptions in our last title using the information from this site:

http://beefchunk.com/documentation/sys-programming/os-win32/debug/www.debuginfo.com/articles/effminidumps.html

And to catch the unhandled exceptions on windows have a look at:

SetUnhandledExceptionFilter (http://msdn.microsoft.com/en-us/library/ms680634%28VS.85%29.aspx).

As an aisde, we spent a lot of time experimenting with the different levels of minidump until we settled on one. This proved to be of no real use in real world crashes as we had no idea what they would be at the time the minidumps were implemented. It's very application specific, and also crash specific, so my recommendation is to add the minidump handler as early as possible, it will grow with the project and through QA and it will be a life saver at somepoint (and hopefully out in the real world too).

Qt C++ Unhandled exceptions stack trace

The stack trace you posted for badFunc is perfectly fine, and the expected result, given the implementation you are using. MiniDumpWriteDump runs a stack trace using the current instruction pointer, unless you are passing the SEH exception's EXCEPTION_POINTERS through the MINIDUMP_EXCEPTION_INFORMATION structure. Since the unhandled exception filter is installed at the bottom of the exception frames, calling MiniDumpWriteDump from there produces the stack trace you observed.

To get a more helpful stack trace, you need to pass the EXCEPTION_POINTERS to MiniDumpWriteDump.

This is just one of many issues with the implementation you are using. There are more:

  • The author seems to be well aware, that they can pass nullptr for the ExceptionParam parameter, but then moves on to decide to always pass nullptr. The interface should really provide two overloads: One that takes an EXCEPTION_POINTERS argument, and one without. This allows the functionality to be called from anywhere, but also retains the stack trace, when called from an unhandled exception filter (the latter is by far the most common use case).
  • The author raises an "interesting question: what should be done with other threads in the application?" As it stands, MiniDumpWriteDump already suspends all threads in the process before moving forward. You don't even have a choice there. The entire implementation to suspend threads (including the filter to exclude the helper thread) is superfluous. It needs to go.
  • The author fails to address a real issue (both of the vanilla MiniDumpWriteDump, as well as their own thread suspending implementation): Threads get suspended at arbitrary points. If any of these threads hold any locks (like the global heap allocation mutex), you are in for an instant dead lock. After all, MiniDumpWriteDump will want to allocate memory from the process heap as well. The solution here is more involved: The call to MiniDumpWriteDump must be performed in its own process, with appropriate IPC in place.

Either of the above is a fairly substantial bug, and needs to be addressed. As published, the code is both useless as well as dangerous. If you feel like implementing your own solution in the meantime, have a look at the following resources for reliable information:

  • Effective Minidumps - Part 1
  • Effective Minidumps - Part 2

How do I find where an exception was thrown in C++?

Here's some info that may be of use in debugging your problem

If an exception is uncaught, the special library function std::terminate() is automatically called. Terminate is actually a pointer to a function and default value is the Standard C library function std::abort(). If no cleanups occur for an uncaught exception, it may actually be helpful in debugging this problem as no destructors are called.

†It is implementation-defined whether or not the stack is unwound before std::terminate() is called.


A call to abort() is often useful in generating a core dump that can be analyzed to determine the cause of the exception. Make sure that you enable core dumps via ulimit -c unlimited (Linux).


You can install your own terminate() function by using std::set_terminate(). You should be able to set a breakpoint on your terminate function in gdb. You may be able to generate a stack backtrace from your terminate() function and this backtrace may help in identifying the location of the exception.

There is a brief discussion on uncaught exceptions in Bruce Eckel's Thinking in C++, 2nd Ed that may be helpful as well.


Since terminate() calls abort() by default (which will cause a SIGABRT signal by default), you may be able to set a SIGABRT handler and then print a stack backtrace from within the signal handler. This backtrace may help in identifying the location of the exception.


Note: I say may because C++ supports non-local error handling through the use of language constructs to separate error handling and reporting code from ordinary code. The catch block can be, and often is, located in a different function/method than the point of throwing. It has also been pointed out to me in the comments (thanks Dan) that it is implementation-defined whether or not the stack is unwound before terminate() is called.

Update: I threw together a Linux test program called that generates a backtrace in a terminate() function set via set_terminate() and another in a signal handler for SIGABRT. Both backtraces correctly show the location of the unhandled exception.

Update 2: Thanks to a blog post on Catching uncaught exceptions within terminate, I learned a few new tricks; including the re-throwing of the uncaught exception within the terminate handler. It is important to note that the empty throw statement within the custom terminate handler works with GCC and is not a portable solution.

Code:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_GNU
#define __USE_GNU
#endif

#include <execinfo.h>
#include <signal.h>
#include <string.h>

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

void my_terminate(void);

namespace {
// invoke set_terminate as part of global constant initialization
static const bool SET_TERMINATE = std::set_terminate(my_terminate);
}

// This structure mirrors the one found in /usr/include/asm/ucontext.h
typedef struct _sig_ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
} sig_ucontext_t;

void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext) {
sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;

// Get the address at the time the signal was raised from the EIP (x86)
void * caller_address = (void *) uc->uc_mcontext.eip;

std::cerr << "signal " << sig_num
<< " (" << strsignal(sig_num) << "), address is "
<< info->si_addr << " from "
<< caller_address << std::endl;

void * array[50];
int size = backtrace(array, 50);

std::cerr << __FUNCTION__ << " backtrace returned "
<< size << " frames\n\n";

// overwrite sigaction with caller's address
array[1] = caller_address;

char ** messages = backtrace_symbols(array, size);

// skip first stack frame (points here)
for (int i = 1; i < size && messages != NULL; ++i) {
std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
}
std::cerr << std::endl;

free(messages);

exit(EXIT_FAILURE);
}

void my_terminate() {
static bool tried_throw = false;

try {
// try once to re-throw currently active exception
if (!tried_throw++) throw;
}
catch (const std::exception &e) {
std::cerr << __FUNCTION__ << " caught unhandled exception. what(): "
<< e.what() << std::endl;
}
catch (...) {
std::cerr << __FUNCTION__ << " caught unknown/unhandled exception."
<< std::endl;
}

void * array[50];
int size = backtrace(array, 50);

std::cerr << __FUNCTION__ << " backtrace returned "
<< size << " frames\n\n";

char ** messages = backtrace_symbols(array, size);

for (int i = 0; i < size && messages != NULL; ++i) {
std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
}
std::cerr << std::endl;

free(messages);

abort();
}

int throw_exception() {
// throw an unhandled runtime error
throw std::runtime_error("RUNTIME ERROR!");
return 0;
}

int foo2() {
throw_exception();
return 0;
}

int foo1() {
foo2();
return 0;
}

int main(int argc, char ** argv) {
struct sigaction sigact;

sigact.sa_sigaction = crit_err_hdlr;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;

if (sigaction(SIGABRT, &sigact, (struct sigaction *)NULL) != 0) {
std::cerr << "error setting handler for signal " << SIGABRT
<< " (" << strsignal(SIGABRT) << ")\n";
exit(EXIT_FAILURE);
}

foo1();

exit(EXIT_SUCCESS);
}

Output:


my_terminate caught unhanded exception. what(): RUNTIME ERROR!
my_terminate backtrace returned 10 frames

[bt]: (0) ./test(my_terminate__Fv+0x1a) [0x8048e52]
[bt]: (1) /usr/lib/libstdc++-libc6.2-2.so.3 [0x40045baa]
[bt]: (2) /usr/lib/libstdc++-libc6.2-2.so.3 [0x400468e5]
[bt]: (3) /usr/lib/libstdc++-libc6.2-2.so.3(__rethrow+0xaf) [0x40046bdf]
[bt]: (4) ./test(throw_exception__Fv+0x68) [0x8049008]
[bt]: (5) ./test(foo2__Fv+0xb) [0x8049043]
[bt]: (6) ./test(foo1__Fv+0xb) [0x8049057]
[bt]: (7) ./test(main+0xc1) [0x8049121]
[bt]: (8) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (9) ./test(__eh_alloc+0x3d) [0x8048b21]

signal 6 (Aborted), address is 0x1239 from 0x42029331
crit_err_hdlr backtrace returned 13 frames

[bt]: (1) ./test(kill+0x11) [0x42029331]
[bt]: (2) ./test(abort+0x16e) [0x4202a8c2]
[bt]: (3) ./test [0x8048f9f]
[bt]: (4) /usr/lib/libstdc++-libc6.2-2.so.3 [0x40045baa]
[bt]: (5) /usr/lib/libstdc++-libc6.2-2.so.3 [0x400468e5]
[bt]: (6) /usr/lib/libstdc++-libc6.2-2.so.3(__rethrow+0xaf) [0x40046bdf]
[bt]: (7) ./test(throw_exception__Fv+0x68) [0x8049008]
[bt]: (8) ./test(foo2__Fv+0xb) [0x8049043]
[bt]: (9) ./test(foo1__Fv+0xb) [0x8049057]
[bt]: (10) ./test(main+0xc1) [0x8049121]
[bt]: (11) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (12) ./test(__eh_alloc+0x3d) [0x8048b21]

C# Catch Unhandled Exception Down the Call Stack

Yes its possible. Simply surround the top most function call with a try catch. Any exceptions will be thrown all the way out. However you should catch it in the function it occurs and, assuming you can, fix the cause of the exception inside that function. If you can't you program must fail because it can not accomplish the task.

For example, if the file is corrupted the program should fail; if the file has a lock on it from another process you can wait until the lock is released (assuming it is ever released) before continuing or otherwise fail out.

Who prints exception stack trace in case of unhandled exceptions in java?

If an exception isn't caught explicitly in Java (by a catch block) in the code that you're looking at, then the following will happen:

  • The exception will propagate up the call stack until it finds another catch block to handle it. If so, great. If it gets to the top of the stack and there's no catch block to handle it, then:

  • It's handled by whatever is specified as the uncaught exception handler for that thread. This is a block of code that's explicitly set to run if this scenario occurs. If no handler is specified, then:

  • It will call uncaughtException() on ThreadGroup. As per its Javadoc, this does the following:

    • If this thread group has a parent thread group, the uncaughtException method of that parent is called with the same two arguments.
    • Otherwise, this method checks to see if there is a default uncaught exception handler installed, and if so, its uncaughtException method is called with the same two arguments.
    • Otherwise, this method determines if the Throwable argument is an instance of ThreadDeath. If so, nothing special is done. Otherwise, a message containing the thread's name, as returned from the thread's getName method, and a stack backtrace, using the Throwable's printStackTrace method, is printed to the standard error stream.

The bolding is mine, and that's the behaviour that's responsible, by default, for printing your stack trace.

As an aside, you can actually verify that last part if you so wish - something like this will print a (short) stack trace, as you'd expect:

public static void main(String[] args) throws Throwable {
throw new Throwable();
}

Exception in thread "main" java.lang.Throwable
at javaapplication6.JavaApplication6.main(JavaApplication6.java:18)

Yet as per the above docs, this doesn't print anything:

public static void main(String[] args) throws Throwable {
throw new ThreadDeath();
}

How to show a stack trace reports of unhandled exceptions in WPF

I might not have understood this question because to my understanding, it seems to be quite a simple question. There is a StackTrace property on the Exception class. You can get the stack trace from that property:

private void OnDispatcherUnhandledException(object sender, 
System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
string stackTrace = e.Exception.StackTrace;
}

You can find out more from the Exception class page on MSDN. Please let me know if I have misunderstood your problem.



Related Topics



Leave a reply



Submit