Files
2025-10-25 03:02:53 +03:00

238 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[except.handle]
# 14 Exception handling [[except]](./#except)
## 14.4 Handling an exception [except.handle]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L500)
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") in a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") describes the type(s) of exceptions that can cause
that[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") to be entered[.](#1.sentence-1)
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") shall not denote an incomplete type, an abstract class type, or an rvalue reference type[.](#1.sentence-2)
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") shall not denote a pointer or reference to an
incomplete type, other than “pointer to cv void”[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L521)
A handler of type“array of T” orfunction type T is adjusted to be of type
“pointer to T”[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L530)
A[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") is a match for
an exception object
of typeE if
- [(3.1)](#3.1)
The [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") is of type cv T orcv T& andE and T are the same type (ignoring the top-level [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s*), or
- [(3.2)](#3.2)
the [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") is of type cv T orcv T& andT is an unambiguous public base class of E, or
- [(3.3)](#3.3)
the [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type andE is a pointer or pointer-to-member type
that can be converted to T by one or more of
* [(3.3.1)](#3.3.1)
a standard [pointer conversion](conv.ptr "7.3.12Pointer conversions[conv.ptr]") not involving conversions
to pointers to private or protected or ambiguous classes
* [(3.3.2)](#3.3.2)
a [function pointer conversion](conv.fctptr "7.3.14Function pointer conversions[conv.fctptr]")
* [(3.3.3)](#3.3.3)
a [qualification conversion](conv.qual "7.3.6Qualification conversions[conv.qual]"), or
- [(3.4)](#3.4)
the [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type and E is std::nullptr_t[.](#3.sentence-1)
[*Note [1](#note-1)*:
A[*throw-expression*](expr.throw#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") whose operand is an integer literal with value zero does not match a handler of
pointer or pointer-to-member type[.](#3.sentence-2)
A handler of reference to array or function type
is never a match for any exception object ([[expr.throw]](expr.throw "7.6.18Throwing an exception"))[.](#3.sentence-3)
— *end note*]
[*Example [1](#example-1)*: class Matherr { /* ... */ virtual void vf(); };class Overflow: public Matherr { /* ... */ };class Underflow: public Matherr { /* ... */ };class Zerodivide: public Matherr { /* ... */ };
void f() {try { g(); } catch (Overflow oo) {// ...} catch (Matherr mm) {// ...}}
Here, theOverflow handler will catch exceptions of typeOverflow and theMatherr handler will catch exceptions of typeMatherr and of all types publicly derived fromMatherr including exceptions of typeUnderflow andZerodivide[.](#3.sentence-4)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L611)
The handlers for a try block are tried in order of appearance[.](#4.sentence-1)
[*Note [2](#note-2)*:
This makes it possible to write handlers that can never be
executed, for example by placing a handler for a final derived class after
a handler for a corresponding unambiguous public base class[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L619)
A... in a handler's[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") specifies a match for any exception[.](#5.sentence-1)
If present, a... handler shall be the last handler for its try block[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L629)
If no match is found among the handlers for a try block,
the search for a matching
handler continues in a dynamically surrounding try block
of the same thread[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L635)
If the search for a handler
exits the function body of a function with a
non-throwing exception specification,
the function std::terminate ([[except.terminate]](except.terminate "14.6.2The std::terminate function")) is invoked[.](#7.sentence-1)
[*Note [3](#note-3)*:
An implementation is not permitted to reject an expression merely because, when
executed, it throws or might
throw an exception from a function with a non-throwing exception specification[.](#7.sentence-2)
— *end note*]
[*Example [2](#example-2)*: extern void f(); // potentially-throwingvoid g() noexcept { f(); // valid, even if f throwsthrow 42; // valid, effectively a call to std::terminate}
The call tof is well-formed despite the possibility for it to throw an exception[.](#7.sentence-3)
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L661)
If no matching handler is found,
the function std::terminate is invoked;
whether or not the stack is unwound before this invocation ofstd::terminate is implementation-defined ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L669)
A handler is considered [*active*](#def:exception_handling,handler,active "14.4Handling an exception[except.handle]") when
initialization is complete for the parameter (if any) of the catch clause[.](#9.sentence-1)
[*Note [4](#note-4)*:
The stack will have been unwound at that point[.](#9.sentence-2)
— *end note*]
Also, an implicit handler is considered active when
the function std::terminate is entered due to a throw[.](#9.sentence-3)
A handler is no longer considered active when the
catch clause exits[.](#9.sentence-4)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L680)
The exception with the most recently activated handler that is
still active is called the[*currently handled exception*](#def:exception_handling,currently_handled_exception "14.4Handling an exception[except.handle]")[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L686)
Referring to any non-static member or base class of an object
in the handler for a[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") of a constructor or destructor for that object results in undefined behavior[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L692)
Exceptions thrown in destructors of objects with static storage duration or in
constructors of objects associated with non-block variables with static storage duration are not caught by a[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") on
the [main function](basic.start.main "6.10.3.1main function[basic.start.main]")[.](#12.sentence-1)
Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") on the initial function of the thread[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L702)
If a return statement ([[stmt.return]](stmt.return "8.8.4The return statement")) appears in a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") of a
constructor, the program is ill-formed[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L708)
The currently handled exception
is rethrown if control reaches the end of a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") of a constructor or destructor[.](#14.sentence-1)
Otherwise, flowing off the end of
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") of a [*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") is equivalent to flowing off the end of
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of that function (see [[stmt.return]](stmt.return "8.8.4The return statement"))[.](#14.sentence-2)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L721)
The variable declared by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]"), of typecv T or cv T&, is initialized from the exception object,
of type E, as follows:
- [(15.1)](#15.1)
if T is a base class of E,
the variable is copy-initialized ([[dcl.init]](dcl.init "9.5Initializers"))
from an lvalue of type T designating the corresponding base class subobject
of the exception object;
- [(15.2)](#15.2)
otherwise, the variable is copy-initialized ([[dcl.init]](dcl.init "9.5Initializers"))
from an lvalue of type E designating the exception object[.](#15.sentence-1)
The lifetime of the variable ends
when the handler exits, after the
destruction of any objects with automatic storage duration initialized
within the handler[.](#15.sentence-2)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L740)
When the handler declares an object,
any changes to that object will not affect the exception object[.](#16.sentence-1)
When the handler declares a reference to an object,
any changes to the referenced object are changes to the
exception object and will have effect should that object be rethrown[.](#16.sentence-2)