Topic: The value of std::uncaught_exception()
Author: restor <akrzemi1@interia.pl>
Date: Wed, 20 May 2009 17:15:09 CST Raw View
Hi,
I believe there is a defect in the following (15.1.7) paragraph of
N2857:
A throw-expression with no operand rethrows the currently handled
exception. The exception is reactivated with the existing temporary;
no new temporary exception object is created. The exception is no
longer considered to be caught; therefore, the value of
std::uncaught_exception() will *again* be true.
The problem is with the word "again", because it implies that before
rethrowing in the exception handler the value of
std::uncaught_exception() was false. Whereas in the basic scenarios it
is the case, in case of multiple exceptions being thrown into the
program, the value of std::uncaught_exception() might be true even in
the exception handler, as per the below example:
void thrower1();
void thrower2();
struct Helper;
void thrower1() try {
Helper hrlp;
throw Ex1();
}
catch( Ex1 & ) {
}
struct Helper {
~Helper() {
try {
thrower2();
}
catch(...) {
};
}
};
void thrower2() try {
throw Ex2();
}
catch( Ex2 & ) {
assert( std::uncaught_exception() == true );
throw;
}
int main() {
thrower1();
return 0;
}
I find it important because I used to think that
std::uncaught_exception() was to detect stack unwinding (which in turn
would provide the ability to implement ON_SCOPE_FAILURE feature), and
the above "again" seams to supportthat incorrect interpretation.
Regards,
&rzej
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Sean Hunt <rideau3@gmail.com>
Date: Wed, 20 May 2009 23:52:43 CST Raw View
On May 20, 5:15 pm, restor <akrze...@interia.pl> wrote:
> Hi,
> I believe there is a defect in the following (15.1.7) paragraph of
> N2857:
>
> A throw-expression with no operand rethrows the currently handled
> exception. The exception is reactivated with the existing temporary;
> no new temporary exception object is created. The exception is no
> longer considered to be caught; therefore, the value of
> std::uncaught_exception() will *again* be true.
>
> The problem is with the word "again", because it implies that before
> rethrowing in the exception handler the value of
> std::uncaught_exception() was false. Whereas in the basic scenarios it
> is the case, in case of multiple exceptions being thrown into the
> program, the value of std::uncaught_exception() might be true even in
> the exception handler, as per the below example:
In your example, an exception is thrown while stack unwinding is in
progress, which will cause program termination. There is no way to
properly handle such a situation - do you destroy the original
exception? Silence the new one? Throw both simultaneously? Since there
is no real answer to the question of what to do, C++ chooses the only
reasonable solution, which is to fail entirely (Boost and now C++1x
offer library mechanisms to encapsulate multiple exceptions into one
object which is a fabulously elegant solution, but that falls outside
the domain of the actual language and its support mechanisms).
uncaught_exception() is primarly intended to ensure that anything that
could throw during stack unwinding doesn't (or that anything
attempting to rethrow when there exists no exception to rethrow
doesn't try - while rare, I have written code that does this).
Sean Hunt
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: restor <akrzemi1@interia.pl>
Date: Thu, 21 May 2009 11:23:09 CST Raw View
> In your example, an exception is thrown while stack unwinding is in
> progress, which will cause program termination. There is no way to
> properly handle such a situation - do you destroy the original
> exception?
I don't believe that my example should cause termination. I include
the code again, as it didn't compile due to the order of definitions,
with some references.
-------------------------
struct Ex1{};
struct Ex2{};
void thrower1();
void thrower2();
struct Helper {
~Helper() {
try {
thrower2();
}
catch(...) {
};
}
};
void thrower1() try {
Helper help; // P1
throw Ex1();
}
catch( Ex1 & ) {
}
void thrower2() try {
throw Ex2(); // P2
}
catch( Ex2 & ) {
assert( std::uncaught_exception() == true );
throw;
}
int main() {
thrower1();
return 0;
}
------------------------------
While the standard says the program will terminate when exception is
thrown out of a destructor it doesn't say it will terminate if an
exception is thrown and caught within the destructor. Actually the
standard isn't clear enough (at lest for me) about this, but a note in
15.2.3 says:
If a destructor called during stack unwinding exits with an exception,
std::terminate is called. So destructors should generally catch
exceptions and not let them propagate out of the destructor.
It somehow implies that destructors can safely call functions that
throw exceptions as long as they are caught before they get out of the
destructor.
Also, the definition of std::uncaught_exception() says
The function std::uncaught_exception() returns true after completing
evaluation of the object to be
thrown until completing the initialization of the exception-
declaration in the matching handler.
**This includes stack unwinding**....
The "This includes stack unwinding" somehow implies that
std::uncaught_exception() sometimes returns true even if we don't
unwind the stack.
Also, the name "stack unwinding" implies that there is something like
"stack winding" and in that case it would be creating automatic
objects. In my example when function thrower1 creates automatic object
"help" (P1). The destructor body somehow creates a scope in the stack
unwinding process where the stack is wound again, and at (P2) function
thrower2 begins a "nested stack unwinding". In conclusion there is
some sort of "exception stack". This may seam a bit imprecise, but it
seams that Microsoft share the same view, as my code executes as I
have described on their compiler.
Thus, I still claim that there may be a "bug" in 15.1.7.
Regards,
&rzej
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]