Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call-stack for exceptions in C++

People also ask

What is exception call stack?

A trace of the method calls is called a stack trace. The stack trace listing provides a way to follow the call stack to the line number in the method where the exception occurs. The StackTrace property returns the frames of the call stack that originate at the location where the exception was thrown.

What is the role of stack in exception handling?

In the C++ exception mechanism, control moves from the throw statement to the first catch statement that can handle the thrown type. When the catch statement is reached, all of the automatic variables that are in scope between the throw and catch statements are destroyed in a process that is known as stack unwinding.

Can you catch exceptions in C?

C itself doesn't support exceptions but you can simulate them to a degree with setjmp and longjmp calls.

Can exception stack trace null?

Yes. If you create a new Exception() and don't throw it, every property except Data and Message will be null.


What you are doing is not good practice. Here's why:

1. It's unnecessary.
If you compile your project in debug mode so that debugging information gets generated, you can easily get backtraces for exception handling in a debugger such as GDB.

2. It's cumbersome.
This is something you have to remember to add to each and every function. If you happen to miss a function, that could cause a great deal of confusion, especially if that were the function that caused the exception. And anyone looking at your code would have to realize what you are doing. Also, I bet you used something like __FUNC__ or __FUNCTION__ or __PRETTY_FUNCTION__, which sadly to say are all non-standard (there is no standard way in C++ to get the name of the function).

3. It's slow.
Exception propagation in C++ is already fairly slow, and adding this logic will only make the codepath slower. This is not an issue if you are using macros to catch and rethrow, where you can easily elide the catch and rethrow in release versions of your code. Otherwise, performance could be a problem.

Good practice
While it may not be good practice to catch and rethrow in each and every function to build up a stack trace, it is good practice to attach the file name, line number, and function name at which the exception was originally thrown. If you use boost::exception with BOOST_THROW_EXCEPTION, you will get this behavior for free. It's also good to attach explanatory information to your exception that will assist in debugging and handling the exception. That said, all of this should occur at the time the exception is constructed; once it is constructed, it should be allowed to propagate to its handler... you shouldn't repeatedly catch and rethrow more than stricly necessary. If you need to catch and rethrow in a particular function to attach some crucial information, that's fine, but catching all exceptions in every function and for the purposes of attaching already available information is just too much.


No, it is deeply horrible, and I don't see why you need a call stack in the exception itself - I find the exception reason, the line number and the filename of the code where the initial exception occurred quite sufficient.

Having said that, if you really must have a stack trace, the thing to do is to generate the call stack info ONCE at the exception throw site. There is no single portable way of doing this, but using something like http://stacktrace.sourceforge.net/ combined with and a similar library for VC++ should not be too difficult.


One solution which may be more graceful is to build a Tracer macro/class. So at the top of each function, you write something like:

TRACE()

and the macro looks something like:

Tracer t(__FUNCTION__);

and the class Tracer adds the function name to a global stack on construction, and removes itself upon destruction. Then that stack is always available to logging or debugging, maintenance is much simpler (one line), and it doesn't incur exception overhead.

Examples of implementations include things like http://www.drdobbs.com/184405270, http://www.codeproject.com/KB/cpp/cmtrace.aspx, and http://www.codeguru.com/cpp/v-s/debug/tracing/article.php/c4429. Also Linux functions like this http://www.linuxjournal.com/article/6391 can do it more natively, as described by this Stack Overflow question: How to generate a stacktrace when my gcc C++ app crashes. ACE's ACE_Stack_Trace may be worth looking at too.

Regardless, the exception-handling method is crude, inflexible, and computationally expensive. Class-construction/macro solutions are much faster and can be compiled out for release builds if desired.


The answer to all your problems is a good debugger, usually http://www.gnu.org/software/gdb/ on linux or Visual Studio on Windows. They can give you stack traces on demand at any point in the program.

Your current method is a real performance and maintenance headache. Debuggers are invented to accomplish your goal, but without the overhead.