Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C/C++

Unchaining Chained Exceptions in C++


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 One shows two functions that include the exceptionsManager macros, and Listing Two shows how the exception can be managed and how to retrieve the stack dump of the caught exceptions.

Listing One

#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 Two

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

Example 1 shows a typical output of the stack dump.

Example 1.

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!

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.


Paolo is a C++ software developer specializing in image analysis and medical image formats. He distributes his products through his web site www.puntoexe.com, and can be contacted at [email protected]


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.