Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should exceptions be chained in C++? [duplicate]

I just finished work on a C++-program where I've implemented my own exceptions (although derived from std::exception). The practice I've applied when one exception causes a chain reaction, propagating the error upwards and giving rise to other exceptions, is to concatenate the error message at each appropriate step across the modules (read classes). I.e. the old exception itself is dropped and a new exception is created, but with a longer error message.

This may have worked for my small program, but I wasn't very satisfied with my approach in the end. For one, line numbers (although not applied at the moment) and file names are not retained except for the last exception; and really that information is of most interest in the first exception.

I figure this could have been handled better by chaining exceptions together; i.e. the old exception is provided in the constructor of the new exception. But how would that be implemented? Does not exceptions die when they go out of scope from the method, thereby preventing one to use exception pointers? And how to copy and store the exception if the exception can be of any derived class?

This ultimately lead me to consider whether chaining exceptions in C++ is such a good idea after all. Perhaps one should just create one exception and then add additional data to that (like I've been doing, but probably in a much better manner)?

What is your response to this? Should exceptions caused by another be chained together to retain a sort of "exception trace" -- and how should that be implemented? -- or should a single exception be used and additional data attached to it -- and how should that be done?

like image 351
gablin Avatar asked Aug 22 '10 22:08

gablin


People also ask

Why do we need exception chaining?

Chained Exception helps to identify a situation in which one exception causes another Exception in an application. For instance, consider a method which throws an ArithmeticException because of an attempt to divide by zero but the actual cause of exception was an I/O error which caused the divisor to be zero.

Where should exceptions be handled?

You should handle the exception at the lowest possible level. If method can't handle the exception properly you should throw it.

Which is most useful method in exception chaining for knowing?

getCause() method :- This method returns actual cause of an exception. initCause(Throwable cause) method :- This method sets the cause for the calling exception.

What do you mean by chained exceptions?

Chained exceptions allow you to rethrow an exception, providing additional information without losing the original cause of the exception. The chained exception API was introduced in 1.4 by adding a cause property of type Throwable to exceptions.


1 Answers

Since this question has been asked noteable changes have been made to the standard with C++11. I am continually missing this in discussions about exceptions, but the following approach, nesting exceptions, does the trick:

Use std::nested_exception and std::throw_with_nested

It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.

Since you can do this with any derived exception class, you can add a lot of information to such a backtrace! You may also take a look at my MWE on GitHub, where a backtrace would look something like this:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
like image 77
GPMueller Avatar answered Oct 18 '22 13:10

GPMueller