When exceptions aren't enough: Dealing with runtime errors.

  • Thread starter Aaron W. LaFramboise
  • Start date
A

Aaron W. LaFramboise

I'm seeking a solution to my C++-life long dilemma of how to deal with
errors when exceptions aren't appropriate. Below I highlight two
error cases, which mainly occur when trying to handle "unexpected"
errors on system interfaces. I am an experienced modern C++
programmer, and I'm mainly interested in the case where the error is
in a generic, reusable component where invasive control over the user
is unacceptable.


Case 1: An error was encountered, but this does not prevent continued
execution.

In these cases, it is generally inappropriate to throw an exception,
and in some situations, due to the nature of the operation, it might
be 'too late' (the operation has already been completed) or impossible
(in a destructor) to throw an exception.

For example, an error is encountered while trying to close a file.
This most commonly happens for files with physical storage on remote
filesystems. Depending on the situation, this may not be a serious
condition by itself.

Another example might be closing a temporary pipe at the completion of
some sort of IPC operation. It may be the case that this failure is
entirely irrelevent, and that execution can (and should) continue.
Yet, the error should be reported, as it may have some relevence.


Case 2: An error was encountered, and it probably will prevent
continued execution.

In these cases, we would like to throw an exception, but we can't,
probably because we're in a destructor.

An example of this would be a class that needs to allocate memory for
some reason in its destructor, and this allocation fails.


Solutions

Well, I haven't found a good one.

Traditional C solutions tend to involve doing something like writing
to stderr, which is not appropriate in the general case for modern
code.

For many of the cases, we want stack-based processing similar to C++
exceptions: we just don't want the part where it kills the current
flow of execution. Resumptions would be perfect for many situations,
yet there seems to be little interest in implementing these for C++.

I'd speculate that this is a fairly common problem, and that it is
fairly common to do the wrong thing, probably on the dubious
nihilistic grounds that "we're screwed anyway" or "i don't care." How
many times does code like this get written:

my_file::~my_file() {
close(file_handle); // not checking return value.. oh well
}


Has anyone found a good solution to these catagories of problems?


Aaron W. LaFramboise
 
I

Ian

Aaron said:
I'm seeking a solution to my C++-life long dilemma of how to deal with
errors when exceptions aren't appropriate. Below I highlight two
error cases, which mainly occur when trying to handle "unexpected"
errors on system interfaces. I am an experienced modern C++
programmer, and I'm mainly interested in the case where the error is
in a generic, reusable component where invasive control over the user
is unacceptable.


Case 1: An error was encountered, but this does not prevent continued
execution.

In these cases, it is generally inappropriate to throw an exception,
and in some situations, due to the nature of the operation, it might
be 'too late' (the operation has already been completed) or impossible
(in a destructor) to throw an exception.

For example, an error is encountered while trying to close a file.
This most commonly happens for files with physical storage on remote
filesystems. Depending on the situation, this may not be a serious
condition by itself.

Another example might be closing a temporary pipe at the completion of
some sort of IPC operation. It may be the case that this failure is
entirely irrelevent, and that execution can (and should) continue.
Yet, the error should be reported, as it may have some relevence.
Log the error in an appropriate place, either you application's log file
if it has one, or via you system's log interface.
Case 2: An error was encountered, and it probably will prevent
continued execution.

In these cases, we would like to throw an exception, but we can't,
probably because we're in a destructor.

An example of this would be a class that needs to allocate memory for
some reason in its destructor, and this allocation fails.
In this case, either assert or throw an exception that is caught in
main, printing a message and aborting.

I prefer the former, at least on a platform where you can leave a core
file for later analysis.

Ian
 
W

wij

Aaron said:
..
Case 1: An error was encountered, but this does not prevent
continued execution.
In these cases, it is generally inappropriate to throw an
exception, and in some situations, due to the nature of the
operation, it might be 'too late' (the operation has already
been completed) or impossible (in a destructor) to throw an
exception.
For example, an error is encountered while trying to close a
file. This most commonly happens for files with physical
storage on remote filesystems. Depending on the situation,
this may not be a serious condition by itself.

I have a developing library, which tries to solve problems
like you mentioned.

http://sourceforge.net/projects/libwx/

Hope it could help. Suggestion and relevant questions are
welcome. IMHO(from articles there), "close" stuff has to
succeed, no matter what it returned.
Case 2: An error was encountered, and it probably will
prevent continued execution. In these cases, we would like
to throw an exception, but we can't, probably because we're
in a destructor. An example of this would be a class that
needs to allocate memory for some reason in its destructor,
and this allocation fails.

It is thought as class design problem, see also the suggested
link.
 
A

Aaron W. LaFramboise

Aaron W. LaFramboise wrote:
Log the error in an appropriate place, either you application's log file
if it has one, or via you system's log interface.

If I am writing a reusable file-handling component, for example, it is
the likely case that the component has no idea what the correct place
is. For example, if you were re-implementing something similar to
std::filebuf, how would you know how to report errors from ~filebuf?

Notice that the standard cleverly (or not) avoids this problem by
ignoring the cause of errors in general (There is no standard way to
find out why filebuf::eek:pen() failed, for example.), and ignoring
failures in close() in the destructor in particular.

In this case, either assert or throw an exception that is caught in
main, printing a message and aborting.

You can't throw from a destructor. assert() is not acceptable because
this is a runtime error, not a logic error. The application should be
able to exit gracefully. A core file is not helpful here, because
there is no bug.


Aaron W. LaFramboise
 
I

Ian

Aaron said:
If I am writing a reusable file-handling component, for example, it is
the likely case that the component has no idea what the correct place
is. For example, if you were re-implementing something similar to
std::filebuf, how would you know how to report errors from ~filebuf?
You could, for your own errors, use a static error member?
Notice that the standard cleverly (or not) avoids this problem by
ignoring the cause of errors in general (There is no standard way to
find out why filebuf::eek:pen() failed, for example.), and ignoring
failures in close() in the destructor in particular.





You can't throw from a destructor. assert() is not acceptable because
this is a runtime error, not a logic error. The application should be
able to exit gracefully. A core file is not helpful here, because
there is no bug.
Well you could if there wasn't anything else to do. With assert, the
error condition could be something outside of the code's control, maybe
a problem with the underlying operating system. So one of the code's
assumptions is false, which is fair grounds for an assert.

Ian
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top