Shachar Shemesh
2015-04-20 03:20:22 UTC
Hi all,
This, I think, is the most sore point in C++ today. Exception nesting.
Current standard mandates that an exception thrown during stack unwind
for another exception causes immediate program termination. This has led
to many suggestions that destructors never throw. I find that suggestion
both problematic and too onerous.
It is problematic because in 99% of the cases, it is quite alright for
destructors to throw. In other words, there are two types of C++
programmers. Those who never heard of the problem, those who think it is
illegal for a destructor to throw, and those... three types of C++
programmers.
This restriction is also too onerous. If an operation that needs to be
done during destruction fails, the programmer is left with zero options
as to what to do about it. There is, in fact, no way for the programmer
to report this failure, or to act about it. The only advice I offer
people (and follow it myself) is: disregard the threat, throw from the
destructor. This effectively places me in the same group as the most
ignorant of the two three.
In fact, this restriction is so onerous, that I have seen code where the
destructor is declared as "nothrow", but also throws. This is obvious
mistake was done by someone aware of the problem, and yet, when push
comes to shove, he needed to report the error somehow.
What I suggest:
The simplest solution to this problem is to simply ignore the new
exception. There are zero cases where the programmer is worse off than
she is today. In all likelihood, the second exception is a byproduct of
the first one anyways.
An alternative solution, but a more complicated one, is to employ
excption chaining, such as the one used by D. This has several
challenges to implement. For one thing, the exception needs to be
chained to something. As long as C++ allows throwing just any ol' thing,
that simply cannot be done. I think a reasonable compromise on that
front is to add a chain pointer to std::exception, and chain the new
exception only if the types line up (i.e. - if both end of chain object
and newly thrown object derive from std::exception).
An even more generic solution (not sure that's a good thing, mind you)
is to define some interface, and allow chaining if the static types line
up. I.e. - if the existing end of chain object has a function called
"chain_exception" that is capable of accepting a pointer to the object
currently being thrown. I'm not confident I understand the exception
mechanism well enough, but I suspect this would incur a run time cost
that is, probably, not worth the trouble.
Personally, I'm perfectly happy with option 1: discard the new
exception. It is simple, easy to implement, covers most of the cases and
has zero down sides compared to the situation as it is today.
All of the above does not refer to errors thrown during construction and
destruction of the exception object itself. Personally, I'm perfectly
fine with leaving the situation there as it is today. It is perfectly
valid, in my eyes, to require greater care from programmers designing
exception objects than from programmers merely using them.
Shachar
This, I think, is the most sore point in C++ today. Exception nesting.
Current standard mandates that an exception thrown during stack unwind
for another exception causes immediate program termination. This has led
to many suggestions that destructors never throw. I find that suggestion
both problematic and too onerous.
It is problematic because in 99% of the cases, it is quite alright for
destructors to throw. In other words, there are two types of C++
programmers. Those who never heard of the problem, those who think it is
illegal for a destructor to throw, and those... three types of C++
programmers.
This restriction is also too onerous. If an operation that needs to be
done during destruction fails, the programmer is left with zero options
as to what to do about it. There is, in fact, no way for the programmer
to report this failure, or to act about it. The only advice I offer
people (and follow it myself) is: disregard the threat, throw from the
destructor. This effectively places me in the same group as the most
ignorant of the two three.
In fact, this restriction is so onerous, that I have seen code where the
destructor is declared as "nothrow", but also throws. This is obvious
mistake was done by someone aware of the problem, and yet, when push
comes to shove, he needed to report the error somehow.
What I suggest:
The simplest solution to this problem is to simply ignore the new
exception. There are zero cases where the programmer is worse off than
she is today. In all likelihood, the second exception is a byproduct of
the first one anyways.
An alternative solution, but a more complicated one, is to employ
excption chaining, such as the one used by D. This has several
challenges to implement. For one thing, the exception needs to be
chained to something. As long as C++ allows throwing just any ol' thing,
that simply cannot be done. I think a reasonable compromise on that
front is to add a chain pointer to std::exception, and chain the new
exception only if the types line up (i.e. - if both end of chain object
and newly thrown object derive from std::exception).
An even more generic solution (not sure that's a good thing, mind you)
is to define some interface, and allow chaining if the static types line
up. I.e. - if the existing end of chain object has a function called
"chain_exception" that is capable of accepting a pointer to the object
currently being thrown. I'm not confident I understand the exception
mechanism well enough, but I suspect this would incur a run time cost
that is, probably, not worth the trouble.
Personally, I'm perfectly happy with option 1: discard the new
exception. It is simple, easy to implement, covers most of the cases and
has zero down sides compared to the situation as it is today.
All of the above does not refer to errors thrown during construction and
destruction of the exception object itself. Personally, I'm perfectly
fine with leaving the situation there as it is today. It is perfectly
valid, in my eyes, to require greater care from programmers designing
exception objects than from programmers merely using them.
Shachar
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.