lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] PATCH: use std::uncaught_exceptions()


From: Vadim Zeitlin
Subject: Re: [lmi] PATCH: use std::uncaught_exceptions()
Date: Sat, 24 Mar 2018 15:36:27 +0100

On Fri, 23 Mar 2018 22:14:02 +0000 Greg Chicares <address@hidden> wrote:

GC> On 2018-03-23 09:17, Vadim Zeitlin wrote:
GC> > 
GC> >  I've made a PR with a trivial change replacing the use of
GC> > std::uncaught_exception() (singular, returning bool) with
GC> > std::uncaught_exceptions() (plural, returning int) as the former is
GC> > deprecated in C++17 in favour of the latter and, in practice, MSVS 2017
GC> > warns about this, which is annoying, so it would be nice if you could
GC> > please apply https://github.com/vadz/lmi/pull/76
GC> 
GC> Cherry-picked; to be pushed after my next complete test.

 Thanks!

GC> In 'handle_exceptions.hpp' I've trivially updated this comment:
GC> 
GC> /// It may seem like a good idea to test std::uncaught_exceptions()
GC> /// right before the try block, as recommended here [these references
GC> /// speak of the related facility deprecated by C++17]:
GC> ///   
http://groups.google.com/group/comp.lang.c++.moderated/msg/ec0ef69dd3949955
GC> ///   "Before the try-block in report_exception, query
GC> ///   std::uncaught_exception() to determine if an exception is
GC> ///   active. If it is not, throw std::logic_error or some exception
GC> ///   that you know that your framework will catch."
GC> /// but actually that's invalid--see:
GC> ///   
http://groups.google.com/group/comp.lang.c++.moderated/msg/aa7ce713ee90c044
GC> ///   "The only problem with uncaught_exception is that it doesn't
GC> ///   tell you when you're in a catch(...) { ... throw; } block"
GC> 
GC> but now I wonder: does this C++17 improvement address exactly the
GC> problem described in the second clc++m citation above?

 I admit I haven't reread all this long thread from 1999, but I don't think
std::uncaught_exceptions() can help with the problem here, at least if I
understand it correctly. And my understanding, gathered from looking at the
commits c31c664, 40d9427 and df4fc26 is that we'd like to check whether
report_exception() is called from a catch clause, in order to prevent the
"throw;" statement in it from invoking std::terminate(). However neither
std::uncaught_exception() nor std::uncaught_exceptions() can be used for
this because both would return 0 when called from a "catch" clause after
throwing a (single) exception, as they only count "live" exceptions and not
the ones being handled.

GC> And if so, should we change 'handle_exceptions.hpp'

 I don't think we should change it. It's true that report_exception() is
dangerous in the sense that using it incorrectly terminates the program,
but in practice this doesn't seem to have been a problem, neither in lmi,
nor in any of my other projects where I use similar functions. And we can
always ensure that all occurrences of the calls to it are found inside
catch blocks only by simple static inspection of the code. So changing it
doesn't seem really necessary and, of course, there is also matter of it
seeming impossible to do.

 So the only change I'd consider would be to explain more clearly in the
comment that we can't use std::uncaught_exception[s]() here, without any
references to the external sources as the real reason for it is very
simple: if we used it, we'd never do anything in this function at all as
uncaught_exception{,s}() would always return {false,0}.


GC> I think the last time I looked at std::uncaught_exception[s]() was
GC> over a decade ago, and I concluded then that it wasn't actually
GC> very useful--but I see you've used it in code written since that
GC> time, so you must have a better understanding of it than I do.

 std::uncaught_exception() is useful, but limited, which does make it not
very useful in practice and std::uncaught_exceptions() removes the
limitation making it very useful indeed. However both of them can only be
used from object destructors in a useful way, to the best of my knowledge.
There they can be used in order to execute cleanup action on scope exit
depending on whether the scope is being left normally (without exception)
or abnormally (due to an exception being thrown). E.g. they allow
implementing Alexandrescu's scope guard class without having an explicit
dismiss() method to prevent it from doing its cleanup on normal exit, so
that it becomes possible to easily define a "rollback" class that only
performs the rollback in its dtor if an exception happened.

 Regards,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]