Nested exceptions (ala Java)

A

Asfand Yar Qazi

Consider the following operation:

class C
{
public:
...
virtual void override_me() = 0;

struct AnException : public std::runtime_error {
AnException(const std::string& arg)
: std::runtime_error(arg)
{}
};

void run_some_operation()
{
try {
...
this->override_me();
...
} catch(const std::exception& e) {
throw AnException(e.what()
+ " raised from 'override_me()' "
+ " in 'run_some_operation()'");
}
}

void run_another_operation()
{
try {
...
this->override_me();
...
} catch(const std::exception& e) {
throw AnException(e.what()
+ " raised from 'override_me()' "
+ " in 'run_another_operation()'");
}
}

...
}; // class C


Now, I was doing some Java a few months ago, and I encountered Java's way of
doing this. Each 'Throwable' has another member, a 'Cause'. So above, the
'Cause' of the 'AnException' would be whatever exception 'override_me()' threw.

In Java, of course, you can get a stack trace to the point where the exception
was thrown, so storing a nested exception allows the nested exception's
stacktrae to also be shown. In the above example, the stacktrace for the
'AnException' would be where it is thrown in the 'run_some_operation()'
function, while the stack trace for the exception that triggered that
exception be from wherever it was thrown. (I hope that's not too confusing.)

Now, in C++ exceptions store stack traces up to the point they were thrown
from (it would be nice if they could...) so nesting exceptions like this isn't
too useful. But it still allows a little bit more detail to be stored, and
avoids having to do some text processing (appending the message of one
exception as well as its name to the message of the other one).

I'm thinking of creating a new base class that all my exceptions derive from
that allows this behaviour. Do you guys think it'd be a useful feature to
immitate? Is there anything I'm not thinking of? (I know I'd need to store a
copy of the exception thrown, which I can't do for standard exceptions. But
my own exceptions will all have a 'virtual copy constructor' that I'll use to
get a duplicate of them to store, so that'll be no problem.)

Thanks, please be gentle with the flames if I'm talking cobblers :)
 
T

TB

Asfand Yar Qazi skrev:
Consider the following operation:

class C
{
public:
...
virtual void override_me() = 0;

struct AnException : public std::runtime_error {
AnException(const std::string& arg)
: std::runtime_error(arg)
{}
};

void run_some_operation()
{
try {
...
this->override_me();
...
} catch(const std::exception& e) {
throw AnException(e.what()
+ " raised from 'override_me()' "
+ " in 'run_some_operation()'");
}
}

C++ is not Java. The statement

e.what() + "..." + "...";

does not do what you think it does.
 
A

Asfand Yar Qazi

TB said:
Asfand Yar Qazi skrev:



C++ is not Java. The statement

e.what() + "..." + "...";

does not do what you think it does.

Yeah, I cobbled the above code together in a few minutes. I know I have do do
a "std::string(e.what()) + ...;

I'm a C++ programmer first, then a Java one if at all! :)
 
A

Alf P. Steinbach

* Asfand Yar Qazi:
>
> [idea of tacking on information to exception passing trough function]

You're not the first to think of that. We've all done it... ;-) With
macros and the whole shebang -- consider where the pressure to add
__func__ and so on comes from (it's the automated info-gathering).

Exception information is useful for mainly two purposes: debugging, and
logging.

Intercepting and rethrowing exceptions helps logging and "manual"
debugging, but interfere with interactive and JIT debuggers such as
those common in Windows programming (in particular, if you step over a
call and an exception occurs, you'd like the debugger to go right to
where that exception originated, not the latest rethrower, which is a
strong low-level-trenches argument for using RAII instead of try-catch).
Also, on the negative side, adding info makes exceptions less
efficient, and it can be very dangerous for that overly dangerous
exception std::bad_alloc. Although, of course, one may argue that the
only reasonable handling of std::bad_alloc is to install a new-handler
that logs the incident, says goodbye, and calls std::exit or std::abort.
 
A

Asfand Yar Qazi

Alf said:
* Asfand Yar Qazi:
[idea of tacking on information to exception passing trough function]

You're not the first to think of that. We've all done it... ;-) With
macros and the whole shebang -- consider where the pressure to add
__func__ and so on comes from (it's the automated info-gathering).

lol. Actually, I was trying to get some input into whether or not Java's way
of 'nesting' exceptions as 'causes' was feasible.
Exception information is useful for mainly two purposes: debugging, and
logging.

Intercepting and rethrowing exceptions helps logging and "manual"
debugging, but interfere with interactive and JIT debuggers such as
those common in Windows programming (in particular, if you step over a
call and an exception occurs, you'd like the debugger to go right to
where that exception originated, not the latest rethrower, which is a
strong low-level-trenches argument for using RAII instead of try-catch).
Also, on the negative side, adding info makes exceptions less
efficient, and it can be very dangerous for that overly dangerous
exception std::bad_alloc. Although, of course, one may argue that the
only reasonable handling of std::bad_alloc is to install a new-handler
that logs the incident, says goodbye, and calls std::exit or std::abort.

Thanks - I will implement my own Exception base class (in fact, I already
have...) I wish there was a way to generate stack traces like in Java with
exceptions - out-side of the debugger of course.

I seem to remember in GCC you have to set a breakpoint to the function
_Unwind_RaiseException and you'd then be able to get a backtrace of where the
exception was about to be thrown.) Wish there was some way of getting
information like this in a standard manner.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top