This is a small part of the discussion going on writing exception safe code in C++ especially for large C++ programs such as ACE/TAO library/frameworks. This snippet is extracted from tens of emails on the topic on the devo-group mailing list of DOC (Distributed Object Computing) group. A major part of this reply was given by Carlos O'Ryan, former student of Dr. Doug Schmidt, a famous CORBA expert.
>> Either use C++ exceptions to propagate errors from constructors
I agree with that.
>> or don't do anything in constructors that can fail and put all such
>> activities in an open() method.
Unfortunately that does not jive well with RAII, a very important C++
idiom.
>> "Swallow errors in destructors".
>>
This is something I always feel queasy about. Yes, I understand why
destructors should not fail (which is a stronger requirement than not
raising exceptions.) However, destructors can and will fail when
dealing with OS resources (or even worse, distributed resources.) What
is one to do?
I think it is a case where a blanket statement is inappropriate. The
developer must choose between equally bad alternatives, and pick the
right one in the context. We all understand that it is impossible to
provide the strong exception guarantee (or the weak one for that matter)
if some destructors can fail. However, in long running systems, errors
can and do happen. At the very least one should provide enough logging
for post-mortem analysis. If you blindly swallow the errors in the
destructor your application will not be supportable in the field. If
you let the exceptions propagate then you cannot offer the strong
exception guarantee. Logging the problems is tempting, but logging is
not always available or appropriate (what if the error was detected
while disconnecting from your logging service or closing the logging
file?)
One should remember why the exception guarantees are desirable. They
simplify the analysis of the program. It is easier to convince oneself
that the system will remain in a consistent state if the transitions
either succeed or fail. One can, however, perform more detailed
analysis when an exception is raised and still argue that the system is
safe.
The trick is for libraries like ACE or TAO. In such libraries it is
impossible to know what the right action is, because it depends on the
context. I would suggest that using hooks is the only viable
alternative in such cases.
>> Either use C++ exceptions to propagate errors from constructors
I agree with that.
>> or don't do anything in constructors that can fail and put all such
>> activities in an open() method.
Unfortunately that does not jive well with RAII, a very important C++
idiom.
>> "Swallow errors in destructors".
>>
This is something I always feel queasy about. Yes, I understand why
destructors should not fail (which is a stronger requirement than not
raising exceptions.) However, destructors can and will fail when
dealing with OS resources (or even worse, distributed resources.) What
is one to do?
I think it is a case where a blanket statement is inappropriate. The
developer must choose between equally bad alternatives, and pick the
right one in the context. We all understand that it is impossible to
provide the strong exception guarantee (or the weak one for that matter)
if some destructors can fail. However, in long running systems, errors
can and do happen. At the very least one should provide enough logging
for post-mortem analysis. If you blindly swallow the errors in the
destructor your application will not be supportable in the field. If
you let the exceptions propagate then you cannot offer the strong
exception guarantee. Logging the problems is tempting, but logging is
not always available or appropriate (what if the error was detected
while disconnecting from your logging service or closing the logging
file?)
One should remember why the exception guarantees are desirable. They
simplify the analysis of the program. It is easier to convince oneself
that the system will remain in a consistent state if the transitions
either succeed or fail. One can, however, perform more detailed
analysis when an exception is raised and still argue that the system is
safe.
The trick is for libraries like ACE or TAO. In such libraries it is
impossible to know what the right action is, because it depends on the
context. I would suggest that using hooks is the only viable
alternative in such cases.
Comments
back again! I never get tired of looking for blogs
just like this one.
Check out my blog, please!
thanks you!
gclub