How to Find Where an Exception Was Thrown in C++

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]

How to know the cause of thrown exception in c++

You can use the Call Stack to see where in your code the program broke.
To display the call stack window, from the menu:

Debug-->Windows-->Call Stack

Then double-click on the top line that corresponds to anything in your own code. This is where your own code made the program break. You can also move to any previous function in the call stack, examine the variables, etc.

In release mode, C++ exceptions do not trace the call stack. You need to design and implement your own exception-handling mechanism.

Finding out the source of an exception in C++ after it is caught?

If you are just interested in where the exception came from, you could just write a simple macro like

#define throwException(message) \
{ \
std::ostringstream oss; \
oss << __FILE __ << " " << __LINE__ << " " \
<< __FUNC__ << " " << message; \
throw std::exception(oss.str().c_str()); \
}

which will add the file name, line number and function name to the exception text (if the compiler provides the respective macros).

Then throw exceptions using

throwException("An unknown enum value has been passed!");

How to know the exact line of code where an exception has been caused?

It seems everyone is trying to improve your code to throw exceptions in your code, and no one is attempting the actual question you asked.

Which is because it can't be done. If the code that's throwing the exception is only presented in binary form (e.g. in a LIB or DLL file), then the line number is gone, and there's no way to connect the object to to a line in the source code.

How to check if a function throws an exception in c#?

You have a lot of options here:

  • This is generally done with a Try... pattern like TryParse.

    bool TryGetFileNames(out List<string> fileNames)
  • You can also return null.

Windows/C++: Is it possible to find the line of code where exception was thrown having Exception Offset

Yes, that's possible. Start debugging with the exact same binaries as ran by your user, make sure the DLL is loaded and you've got a matching PDB file for it. Look in Debug + Windows + Modules for the DLL base address. Add the offset. Debug + Windows + Disassembly and enter the calculated address in the Address field (prefix with 0x). That shows you the exact machine code instruction that caused the exception. Right-click + Go To Source code to see the matching source code line.

While that shows you the statement, this isn't typically good enough to diagnose the cause. The 0xc0000005 exception is an access violation, it has many possible causes. Often you don't even get any code, the program may have jumped into oblivion due to a corrupted stack. Or the real problem is located far away, some pointer manipulation that corrupted the heap. You also typically really need a stack trace that shows you how the program ended up at the statement that bombed.

What you need is a minidump. You can easily get one from your user if she runs Vista or Win7. Start TaskMgr.exe, Processes tab, select the bombed program while it is still displaying the crash dialog. Right-click it and Create Dump File.

To make this smooth, you really want to automate this procedure. You'll find hints in my answer in this thread.

How am i getting Exception thrown error in c

scanf_s("%s", isim);

This line is wrong. You have to specify the buffer size after the pointer to the buffer when you are using scanf_s().

Also don't forget to

  • Include all required headers
  • Define all variables used
  • Initialize all variables before reading

It should be like this:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char isim[1024]; /* declare variables to use */
char name[20] = "name"; /* initialize variables to read */
printf_s("Enter your name:");
scanf_s("%s", isim, (unsigned)_countof(isim)); /* specify the buffer size */
printf_s("Nice to meet you %s",name);
system("pause");
return 0;
}

Find out specific Exception

You can get more information for the particular exception using different methods on it. Here I'm using the System.Diagnostics.Debug class to print in Visual Studio's output console. In your catch block:

using System.Diagnostics;

try
{
// do stuff
}
catch (Exception e)
{
Debug.WriteLine(e.GetType()); // Displays the type of exception
Debug.WriteLine(e.Message()); // Displays the exception message
}

You can see more here: Exception methods &
Exception properties



Related Topics



Leave a reply



Submit