FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
C++
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
TABLE OF CONTENTS
July 25, 2006

Unchaining Chained Exceptions in C++

(Page 3 of 3)

Usage

The body of each function that needs to be monitored must be enclosed by the FUNCTION_START and FUNCTION_END macros. The FUNCTION_START macro also requires a parameter that represents the function's name; it will be used later by FUNCTION_END if a catch and throw happens.

The catch block that is able to process the exception must have a call to exceptionsManager::getExceptionInfo() or exceptionsManager::getMessage(). Both are static methods.

The first method returns a list of exceptionInfo objects that store the information of the catch and throw points traversed by the exception, and the second method returns a string with a text representation of the objects returned by getExceptionInfo(). Both the methods clear the information list, so subsequent calls to getExceptionInfo() or getMessage() will return an empty list or an empty string.

When throwing an exception, the application's code should use the macro FUNCTION_THROW (although is not necessary), which also logs some information related to the place where the original throw happened.

The library can be compiled on Windows (you have to define the preprocessor symbol WIN32) and on Posix systems.

Example

The complete source code includes the exceptionsManager class, the related macros and a simple console application that executes an integer division between two parameters.

When an exception is thrown, then all the points traversed by the exception are logged and finally displayed on the screen by the outer catch statement. You can try the application and make it fail by specifying less or more than two parameters, or trying to divide by zero.

Listing 1 shows two functions that include the exceptionsManager macros, and Listing 2 shows how the exception can be managed and how to retrieve the stack dump of the caught exceptions.

#include "exception.h"

//...

int function1(int left, int right) { FUNCTION_START("function1"); if(right==0) { throw std::runtime_error("Ops, dividing by 0!"); } return left/right; FUNCTION_END(); }

int function0(int left, int right) { FUNCTION_START("function0"); return function1(left, right); FUNCTION_END(); }

Listing 1.

try
{
  return function0(param0, param1);
}
catch(std::runtime_error&)
{
  std::cout << "An error occurred. Stack dump:\n";
  std::cout << exceptionsManager::getMessage();
}

Listing 2.

Example 1 shows a typical output of the stack dump.

c:\>cuj.exe 10 0

An error occurred. Stack dump:

[function1] file: c:\sourcecode\cuj\cuj.cpp line: 25 exception type: class std::runtime_error exception message: Ops, dividing by 0!

[function1] file: c:\sourcecode\cuj\cuj.cpp line: 28 exception type: class std::runtime_error exception message: Ops, dividing by 0!

[function0] file: c:\sourcecode\cuj\cuj.cpp line: 37 exception type: class std::runtime_error exception message: Ops, dividing by 0!

Example 1: Typical output of the stack dump.

Conclusion

The exceptionsManager class and the related macros achieve the same results as chained exceptions, but without the problems introduced by chained exceptions.

You don't have to change your code; your catch statements can continue to look for the same kind of exceptions. There are no exceptions wrapped inside other exceptions, and everything works as it did before.

While it is true that you have to insert the two macros in the functions that have to be monitored, this is also true with chained exceptions, so the overall amount of effort is comparable in the two approaches.

Previous Page | 1 The Problem | 2 The Solution | 3 Usage
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK