Nikos Athanasiou
Nikos Athanasiou

Reputation: 31519

How does std::uncaught_exception work?

Intro

There are posts and articles on the usage and the rational of std::uncaught_exception.

The Functionality provided by this function boils down to

std::uncaught_exception detects if stack unwinding is currently in progress.

Q

When searching for its definition all I see is a call to a DLL

_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL uncaught_exception();

How can this level of introspection in a program be achieved ? Is this something implementable by mere c++ or compiler / assembly magic must come into play?

Upvotes: 1

Views: 486

Answers (2)

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

It's compiler magic, although it doesn't need to be written in assembly. The compiler just has to be able to access some global state that is part of the language run-time environment. That state may not be available to your program, but the compiler knows how to access it.

There's a C++ ABI originally written for the Itanium platform but also used by several vendors on other targets as the de facto standard ABI. The ABI defines several functions and types that are not part of standard C++ but are provided by any C++ run-time environment that conforms to the Itanium ABI, and the compiler generates calls to those functions in order to implement features such as exception handling, dynamic memory (de)allocation, RTTI etc.

The exception handling section specifies that there must be a global structure of type __cxa_eh_globals for each thread and all that's needed to implement uncaught_exception() is to see whether the uncaughtExceptions member of the current thread's structure is non-zero.

Obviously the details above apply to compilers conforming to that ABI, but for other compilers with different ABIs there will be something similar, probably not published or documented publicly, but usable by the compiler itself.

Upvotes: 5

Kerrek SB
Kerrek SB

Reputation: 477040

As you can see, uncaught_exception is part of the "Language Support" part of the library (Clause 18, [language.support]). That is to say, it is a library feature that is required to access some aspect of the core language (similar to things like type identification and initializer lists).

Implementing the language support library usually requires compiler-specific knowledge of an appropriate set of compiler intrinsics that expose the relevant aspect of the core language. (You cannot really build a completely compiler-agnostic, "portable" C++ standard library implementation; the standard library is always tied to the platform to some extent because of these language support features. There are even other such situations outside Clause 18, e.g. type traits.)

Exception handling itself is built into the core language and forms a large part of the compiler's ABI; part of this is detecting whether an exception is currently active. You already need this information in order to terminate if a second exception is thrown while the first one is active, so it's just a matter of exposing this state somehow.

Upvotes: 3

Related Questions