177 lines
8.3 KiB
Markdown
177 lines
8.3 KiB
Markdown
[except.throw]
|
||
|
||
# 14 Exception handling [[except]](./#except)
|
||
|
||
## 14.2 Throwing an exception [except.throw]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L192)
|
||
|
||
Throwing an exception transfers control to a handler[.](#1.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
An exception can be thrown from one of the following contexts:[*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]")*s* ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")),
|
||
allocation functions ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")),dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")),typeid ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), and standard library
|
||
functions ([[structure.specifications]](structure.specifications "16.3.2.4 Detailed specifications"))[.](#1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
An object is passed and the type of that object determines which handlers
|
||
can catch it[.](#1.sentence-3)
|
||
|
||
[*Example [1](#example-1)*:
|
||
|
||
throw "Help!"; can be caught by a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ofconstchar* type:try {// ...} catch(const char* p) {// handle character string exceptions here} andclass Overflow {public: Overflow(char,double,double);};
|
||
|
||
void f(double x) {throw Overflow('+',x,3.45e107);} can be caught by a handler for exceptions of typeOverflow:try { f(1.2);} catch(Overflow& oo) {// handle exceptions of type Overflow here}
|
||
|
||
â *end example*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L244)
|
||
|
||
When an exception is thrown, control is transferred to the nearest handler with
|
||
a matching type ([[except.handle]](except.handle "14.4 Handling an exception")); ânearestâ means the handler
|
||
for which the[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") or[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]") following thetry keyword was most recently entered by the thread of control and not yet exited[.](#2.sentence-1)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L257)
|
||
|
||
Throwing an exception
|
||
initializes an object with dynamic storage duration,
|
||
called the[*exception object*](#def:exception_handling,exception_object "14.2 Throwing an exception [except.throw]")[.](#3.sentence-1)
|
||
|
||
If the type of the exception object would be
|
||
an incomplete type ([[basic.types.general]](basic.types.general "6.9.1 General")),
|
||
an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract classes")),
|
||
or a pointer to an incomplete type other thancv void ([[basic.compound]](basic.compound "6.9.4 Compound types")),
|
||
the program is ill-formed[.](#3.sentence-2)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L269)
|
||
|
||
The memory for the exception object is
|
||
allocated in an unspecified way, except as noted in [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")[.](#4.sentence-1)
|
||
|
||
If a handler exits by rethrowing, control is passed to another handler for
|
||
the same exception object[.](#4.sentence-2)
|
||
|
||
The points of potential destruction for the exception object are:
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
when an active handler for the exception exits by
|
||
any means other than
|
||
rethrowing,
|
||
immediately after the destruction of the object (if any)
|
||
declared in the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") in the handler;
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
when an object of type [std::exception_ptr](propagation#lib:exception_ptr "17.9.7 Exception propagation [propagation]") that refers to the exception object is destroyed,
|
||
before the destructor of std::exception_ptr returns[.](#4.sentence-3)
|
||
|
||
Among all points of potential destruction for the exception object,
|
||
there is an unspecified last one
|
||
where the exception object is destroyed[.](#4.sentence-4)
|
||
|
||
All other points [happen before](intro.races#def:happens_before "6.10.2.2 Data races [intro.races]") that last one[.](#4.sentence-5)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
No other thread synchronization is implied in exception handling[.](#4.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
The implementation may then
|
||
deallocate the memory for the exception object; any such deallocation
|
||
is done in an unspecified way[.](#4.sentence-7)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
A thrown exception does not
|
||
propagate to other threads unless caught, stored, and rethrown using
|
||
appropriate library functions; see [[propagation]](propagation "17.9.7 Exception propagation") and [[futures]](futures "32.10 Futures")[.](#4.sentence-8)
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L308)
|
||
|
||
Let T denote the type of the exception object[.](#5.sentence-1)
|
||
|
||
Copy-initialization of an object of type T from
|
||
an lvalue of type const T in a context unrelated to T shall be well-formed[.](#5.sentence-2)
|
||
|
||
If T is a class type,
|
||
the selected constructor is odr-used ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")) and
|
||
the destructor of T is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#5.sentence-3)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L319)
|
||
|
||
An exception is considered [*uncaught*](#def:uncaught_exception "14.2 Throwing an exception [except.throw]") after completing the initialization of the exception object
|
||
until completing the activation of a handler for the exception ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#6.sentence-1)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
As a consequence, an exception is considered uncaught
|
||
during any stack unwinding resulting from it being thrown[.](#6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L329)
|
||
|
||
If an exception is rethrown ([[expr.throw]](expr.throw "7.6.18 Throwing an exception"), [[propagation]](propagation "17.9.7 Exception propagation")),
|
||
it is considered uncaught from the point of rethrow
|
||
until the rethrown exception is caught[.](#7.sentence-1)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
The function std::uncaught_exceptions ([[uncaught.exceptions]](uncaught.exceptions "17.9.6 uncaught_exceptions"))
|
||
returns the number of uncaught exceptions in the current thread[.](#7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L339)
|
||
|
||
An exception is considered caught when a handler for that exception
|
||
becomes [active](except.handle#def:exception_handling,handler,active "14.4 Handling an exception [except.handle]")[.](#8.sentence-1)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
An exception can have active handlers and still be considered uncaught if
|
||
it is rethrown[.](#8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L349)
|
||
|
||
If the exception handling mechanism
|
||
handling an uncaught exception
|
||
directly invokes a function that exits via an
|
||
exception, the function [std::terminate](except.terminate "14.6.2 The std::terminate function [except.terminate]") is invoked[.](#9.sentence-1)
|
||
|
||
[*Example [2](#example-2)*: struct C { C() { } C(const C&) {if (std::uncaught_exceptions()) {throw 0; // throw during copy to handler's [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") object ([[except.handle]](except.handle "14.4 Handling an exception"))}}};
|
||
|
||
int main() {try {throw C(); // calls std::terminate if construction of the handler's// [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") object is not elided ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))} catch(C) { }} â *end example*]
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
If a destructor directly invoked by stack unwinding exits via an exception,std::terminate is invoked[.](#9.sentence-2)
|
||
|
||
â *end note*]
|