Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why will std::uncaught_exception change to std::uncaught_exceptions?

I just noticed over on

http://en.cppreference.com/w/cpp/error/uncaught_exception

that C++17 will replace std::uncaught_exception(), which returns a bool, with std::uncaught_exceptions(), which returns an int.

The addition to the standard describing this is here:

http://isocpp.org/files/papers/n4259.pdf

It doesn't provide the rationale but it does say

[Note: When uncaught_exceptions() > 0, throwing an exception can result in a call of std::terminate() (15.5.1). – end note]

which is oddly vague.

What is the reason for this change? Will multiple active exceptions be possible in C++17 or some future version of the standard?

like image 770
Praxeolitic Avatar asked Jan 02 '15 11:01

Praxeolitic


People also ask

What is an uncaught exception in C++?

If an exception is not caught, it is intercepted by a function called the uncaught exception handler. The uncaught exception handler always causes the program to exit but may perform some task before this happens.

What is STD termination?

std::terminate() is called by the C++ runtime when the program cannot continue for any of the following reasons: 1) an exception is thrown and not caught (it is implementation-defined whether any stack unwinding is done in this case)

How do you catch all exceptions in C++?

Exception handling is used to handle the exceptions. We can use try catch block to protect the code. Catch block is used to catch all types of exception. The keyword “catch” is used to catch exceptions.

What function is called when an uncaught exception is thrown C++?

This function, provided by the default C++ library, defines the behavior when an uncaught exception arises. By default, unexpected calls terminate(). The terminate function defines the actions that are to be performed during process termination. This, by default, calls abort().


1 Answers

The paper that introduced this was n4152, which has the rationale (which generally boils down to "make ScopeGuard work")

To quote,

as documented at least since 1998 in Guru of the Week #47, it means code that is transitively called from a destructor that could itself be invoked during stack unwinding cannot correctly detect whether it itself is actually being called as part of unwinding. Once you’re in unwinding of any exception, to uncaught_exception everything looks like unwinding, even if there is more than one active exception.

And

this uses information already present in major implementations, where current implementations of ScopeGuard resort to nonportable code that relies on undocumented compiler features to make ScopeGuard “portable in practice” today. This option proposes adding a single new function to expose the information that already present in compilers, so that these uses can be truly portable

PS: Here's an example of how this function can be implemented using compiler-speicific information: https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp

And for a simple example where it's used, look no further than boost.log's "record pump" (see boost/log/detail/format.hpp and boost/log/sources/record_ostream.hpp): it makes it possible for BOOST_LOG(lg) << foo(); to log in the destructor of the guard object it creates if foo doesn't throw, that is, if the number of exceptions in flight when the destructor is called is not greater than when the constructor was called.

like image 164
Cubbi Avatar answered Nov 07 '22 12:11

Cubbi