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

1781 lines
77 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.

[basic.exec]
# 6 Basics [[basic]](./#basic)
## 6.10 Program execution [basic.exec]
### [6.10.1](#intro.execution) Sequential execution [[intro.execution]](intro.execution)
[1](#intro.execution-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6225)
An instance of each object with [automatic storage
duration](basic.stc.auto "6.8.6.4Automatic storage duration[basic.stc.auto]") is associated with each entry into its
block[.](#intro.execution-1.sentence-1)
Such an object exists and retains its last-stored value during
the execution of the block and while the block is suspended (by a call
of a function, suspension of a coroutine ([[expr.await]](expr.await "7.6.2.4Await")), or receipt of a signal)[.](#intro.execution-1.sentence-2)
[2](#intro.execution-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6232)
A [*constituent expression*](#def:constituent_expression "6.10.1Sequential execution[intro.execution]") is defined as follows:
- [(2.1)](#intro.execution-2.1)
The constituent expression of an expression is that expression[.](#intro.execution-2.1.sentence-1)
- [(2.2)](#intro.execution-2.2)
The constituent expression of a conversion is
the corresponding implicit function call, if any, or
the converted expression otherwise[.](#intro.execution-2.2.sentence-1)
- [(2.3)](#intro.execution-2.3)
The constituent expressions of a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") or
of a (possibly parenthesized) [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") are the constituent expressions of the elements of the respective list[.](#intro.execution-2.3.sentence-1)
- [(2.4)](#intro.execution-2.4)
The constituent expressions of a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") are the constituent expressions of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#intro.execution-2.4.sentence-1)
[*Example [1](#intro.execution-example-1)*: struct A { int x; };struct B { int y; struct A a; };
B b = { 5, { 1+1 } };
The constituent expressions of the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") used for the initialization of b are 5 and 1+1[.](#intro.execution-2.sentence-2)
— *end example*]
[3](#intro.execution-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6260)
The [*immediate subexpressions*](#def:immediate_subexpression "6.10.1Sequential execution[intro.execution]") of an expression E are
- [(3.1)](#intro.execution-3.1)
the constituent expressions of E's operands ([[expr.prop]](expr.prop "7.2Properties of expressions")),
- [(3.2)](#intro.execution-3.2)
any function call that E implicitly invokes,
- [(3.3)](#intro.execution-3.3)
if E is a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions")),
the initialization of the entities captured by copy and
the constituent expressions of the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") of the [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s*,
- [(3.4)](#intro.execution-3.4)
if E is a [function call](expr.call "7.6.1.3Function call[expr.call]") or implicitly invokes a function,
the constituent expressions of each default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
used in the call, or
- [(3.5)](#intro.execution-3.5)
if E creates an aggregate object ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")),
the constituent expressions of each default member initializer ([[class.mem]](class.mem "11.4Class members"))
used in the initialization[.](#intro.execution-3.sentence-1)
[4](#intro.execution-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6281)
A [*subexpression*](#def:subexpression "6.10.1Sequential execution[intro.execution]") of an expression E is
an immediate subexpression of E or
a subexpression of an immediate subexpression of E[.](#intro.execution-4.sentence-1)
[*Note [1](#intro.execution-note-1)*:
Expressions appearing in the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") are not subexpressions of the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#intro.execution-4.sentence-2)
— *end note*]
The [*potentially-evaluated subexpressions*](#def:subexpression,potentially-evaluated "6.10.1Sequential execution[intro.execution]") of
an expression, conversion, or [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") E are
- [(4.1)](#intro.execution-4.1)
the constituent expressions of E and
- [(4.2)](#intro.execution-4.2)
the subexpressions thereof that
are not subexpressions of a nested unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3Context dependence"))[.](#intro.execution-4.sentence-3)
[5](#intro.execution-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6299)
A [*full-expression*](#def:full-expression "6.10.1Sequential execution[intro.execution]") is
- [(5.1)](#intro.execution-5.1)
an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]"),
- [(5.2)](#intro.execution-5.2)
a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ([[expr.const]](expr.const "7.7Constant expressions")),
- [(5.3)](#intro.execution-5.3)
an immediate invocation ([[expr.const]](expr.const "7.7Constant expressions")),
- [(5.4)](#intro.execution-5.4)
an [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3Declarators"))
(including such introduced by a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))) or
a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
including the constituent expressions of the initializer,
- [(5.5)](#intro.execution-5.5)
an invocation of a destructor generated at the end of the lifetime
of an object other than a temporary object ([[class.temporary]](class.temporary "6.8.7Temporary objects"))
whose lifetime has not been extended,
- [(5.6)](#intro.execution-5.6)
the predicate of a contract assertion ([[basic.contract]](basic.contract "6.11Contract assertions")), or
- [(5.7)](#intro.execution-5.7)
an expression that is not a subexpression of another expression and
that is not otherwise part of a full-expression[.](#intro.execution-5.sentence-1)
If a language construct is defined to produce an implicit call of a function,
a use of the language construct is considered to be an expression
for the purposes of this definition[.](#intro.execution-5.sentence-2)
Conversions applied to the result of an expression in order to satisfy the requirements
of the language construct in which the expression appears
are also considered to be part of the full-expression[.](#intro.execution-5.sentence-3)
For an initializer, performing the initialization of the entity
(including evaluating default member initializers of an aggregate)
is also considered part of the full-expression[.](#intro.execution-5.sentence-4)
[*Example [2](#intro.execution-example-2)*: struct S { S(int i): I(i) { } // full-expression is initialization of Iint& v() { return I; }~S() noexcept(false) { }private:int I;};
S s1(1); // full-expression comprises call of S::S(int)void f() { S s2 = 2; // full-expression comprises call of S::S(int)if (S(3).v()) // full-expression includes lvalue-to-rvalue and int to bool conversions,// performed before temporary is deleted at end of full-expression{ }bool b = noexcept(S(4)); // exception specification of destructor of S considered for noexcept// full-expression is destruction of s2 at end of block}struct B { B(S = S(0));};
B b[2] = { B(), B() }; // full-expression is the entire initialization// including the destruction of temporaries — *end example*]
[6](#intro.execution-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6360)
[*Note [2](#intro.execution-note-2)*:
The evaluation of a full-expression can include the
evaluation of subexpressions that are not lexically part of the
full-expression[.](#intro.execution-6.sentence-1)
For example, subexpressions involved in evaluating
default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments")) are considered to
be created in the expression that calls the function, not the expression
that defines the default argument[.](#intro.execution-6.sentence-2)
— *end note*]
[7](#intro.execution-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6370)
Reading an object designated by a volatile glvalue ([[basic.lval]](basic.lval "7.2.1Value category")),
modifying an object,
producing an injected declaration ([[expr.const]](expr.const "7.7Constant expressions")),
calling a library I/O function, or
calling a function that does any of those operations
are all [*side effects*](#def:side_effects "6.10.1Sequential execution[intro.execution]"),
which are changes in the state of the execution or translation environment[.](#intro.execution-7.sentence-1)
[*Evaluation*](#def:evaluation "6.10.1Sequential execution[intro.execution]") of an expression (or a
subexpression) in general includes both value computations (including
determining the identity of an object for glvalue evaluation and fetching
a value previously assigned to an object for prvalue evaluation) and
initiation of side effects[.](#intro.execution-7.sentence-2)
When a call to a library I/O function
returns or an access through a volatile glvalue is evaluated, the side
effect is considered complete, even though some external actions implied
by the call (such as the I/O itself) or by the volatile access
may not have completed yet[.](#intro.execution-7.sentence-3)
[8](#intro.execution-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6389)
[*Sequenced before*](#def:sequenced_before "6.10.1Sequential execution[intro.execution]") is an asymmetric, transitive, pair-wise relation between
evaluations executed by a single thread ([[intro.multithread]](#intro.multithread "6.10.2Multi-threaded executions and data races")), which induces
a partial order among those evaluations[.](#intro.execution-8.sentence-1)
Given any two evaluations *A* and*B*, if *A* is sequenced before *B* (or, equivalently, *B* is [*sequenced after*](#def:sequenced_after "6.10.1Sequential execution[intro.execution]") *A*),
then the execution of*A* shall precede the execution of *B*[.](#intro.execution-8.sentence-2)
If *A* is not sequenced
before *B* and *B* is not sequenced before *A*, then *A* and*B* are [*unsequenced*](#def:unsequenced "6.10.1Sequential execution[intro.execution]")[.](#intro.execution-8.sentence-3)
[*Note [3](#intro.execution-note-3)*:
The execution of unsequenced
evaluations can overlap[.](#intro.execution-8.sentence-4)
— *end note*]
Evaluations *A* and *B* are[*indeterminately sequenced*](#def:indeterminately_sequenced "6.10.1Sequential execution[intro.execution]") when either *A* is sequenced before*B* or *B* is sequenced before *A*, but it is unspecified which[.](#intro.execution-8.sentence-5)
[*Note [4](#intro.execution-note-4)*:
Indeterminately sequenced evaluations cannot overlap, but either
can be executed first[.](#intro.execution-8.sentence-6)
— *end note*]
An expression *X* is said to be sequenced before
an expression *Y* if
every value computation and every side effect
associated with the expression *X* is sequenced before
every value computation and every side effect
associated with the expression *Y*[.](#intro.execution-8.sentence-7)
[9](#intro.execution-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6419)
Everyvalue computation andside effect associated with a full-expression is
sequenced before every value computation and side effect associated with the
next full-expression to be evaluated[.](#intro.execution-9.sentence-1)[35](#footnote-35 "As specified in [class.temporary], after a full-expression is evaluated, a sequence of zero or more invocations of destructor functions for temporary objects takes place, usually in reverse order of the construction of each temporary object.")
[10](#intro.execution-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6434)
Except where noted, evaluations of operands of individual operators and
of subexpressions of individual expressions are unsequenced[.](#intro.execution-10.sentence-1)
[*Note [5](#intro.execution-note-5)*:
In an expression that is evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be performed consistently in different
evaluations[.](#intro.execution-10.sentence-2)
— *end note*]
The value computations of the operands of an
operator are sequenced before the value computation of the result of the
operator[.](#intro.execution-10.sentence-3)
The behavior is undefined if
- [(10.1)](#intro.execution-10.1)
a side effect on a memory location ([[intro.memory]](intro.memory "6.8.1Memory model")) or
- [(10.2)](#intro.execution-10.2)
starting or ending the lifetime of an object in a memory location
is unsequenced relative to
- [(10.3)](#intro.execution-10.3)
another side effect on the same memory location,
- [(10.4)](#intro.execution-10.4)
starting or ending the lifetime of an object occupying storage that
overlaps with the memory location, or
- [(10.5)](#intro.execution-10.5)
a value computation using the value of any object in the same memory location,
and the two evaluations are not potentially concurrent ([[intro.multithread]](#intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#intro.execution-10.sentence-4)
[*Note [6](#intro.execution-note-6)*:
Starting the lifetime of an object in a memory location can end the lifetime of
objects in other memory locations ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#intro.execution-10.sentence-5)
— *end note*]
[*Note [7](#intro.execution-note-7)*:
The next subclause imposes similar, but more complex restrictions on
potentially concurrent computations[.](#intro.execution-10.sentence-6)
— *end note*]
[*Example [3](#intro.execution-example-3)*: void g(int i) { i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the value of i is incremented i = i++ + i; // undefined behavior i = i + 1; // the value of i is incrementedunion U { int x, y; } u; (u.x = 1, 0) + (u.y = 2, 0); // undefined behavior} — *end example*]
[11](#intro.execution-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6490)
When invoking a function *f* (whether or not the function is inline),
every argument expression and
the postfix expression designating *f* are sequenced before
every precondition assertion of *f* ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
which in turn are sequenced before
every expression or statement
in the body of *f*,
which in turn are sequenced before
every postcondition assertion of *f*[.](#intro.execution-11.sentence-1)
[12](#intro.execution-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6502)
For each
- [(12.1)](#intro.execution-12.1)
function invocation,
- [(12.2)](#intro.execution-12.2)
evaluation of an [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") ([[expr.await]](expr.await "7.6.2.4Await")), or
- [(12.3)](#intro.execution-12.3)
evaluation of a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing an exception"))
*F*,
each evaluation that does not occur within *F* but is evaluated on the same thread and as part of the same signal handler (if any)
is either sequenced before all evaluations that occur within *F* or sequenced after all evaluations that occur within *F*;[36](#footnote-36 "In other words, function executions do not interleave with each other.") if *F* invokes or resumes a coroutine ([[expr.await]](expr.await "7.6.2.4Await")),
only evaluations
subsequent to the previous suspension (if any) and
prior to the next suspension (if any)
are considered to occur within *F*[.](#intro.execution-12.sentence-1)
[13](#intro.execution-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6524)
Several contexts in C++ cause evaluation of a function call, even
though no corresponding function call syntax appears in the translation
unit[.](#intro.execution-13.sentence-1)
[*Example [4](#intro.execution-example-4)*:
Evaluation of a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") invokes one or more allocation
and constructor functions; see [[expr.new]](expr.new "7.6.2.8New")[.](#intro.execution-13.sentence-2)
For another example,
invocation of a conversion function ([[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions")) can arise in
contexts in which no function call syntax appears[.](#intro.execution-13.sentence-3)
— *end example*]
[14](#intro.execution-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6535)
The sequencing constraints on the execution of the called function (as
described above) are features of the function calls as evaluated,
regardless of the syntax of the expression that calls the function[.](#intro.execution-14.sentence-1)
[15](#intro.execution-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6543)
If a signal handler is executed as a result of a call to the std::raise function, then the execution of the handler is sequenced after the invocation
of the std::raise function and before its return[.](#intro.execution-15.sentence-1)
[*Note [8](#intro.execution-note-8)*:
When a signal is received for another reason, the execution of the
signal handler is usually unsequenced with respect to the rest of the program[.](#intro.execution-15.sentence-2)
— *end note*]
[16](#intro.execution-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6552)
During the evaluation of an expression
as a core constant expression ([[expr.const]](expr.const "7.7Constant expressions")),
evaluations of operands of individual operators and
of subexpressions of individual expressions
that are otherwise either unsequenced or indeterminately sequenced
are evaluated in lexical order[.](#intro.execution-16.sentence-1)
[35)](#footnote-35)[35)](#footnoteref-35)
As specified
in [[class.temporary]](class.temporary "6.8.7Temporary objects"), after a full-expression is evaluated, a sequence of
zero or more invocations of destructor functions for temporary objects takes
place, usually in reverse order of the construction of each temporary object[.](#footnote-35.sentence-1)
[36)](#footnote-36)[36)](#footnoteref-36)
In other words,
function executions do not interleave with each other[.](#footnote-36.sentence-1)
### [6.10.2](#intro.multithread) Multi-threaded executions and data races [[intro.multithread]](intro.multithread)
#### [6.10.2.1](#intro.multithread.general) General [[intro.multithread.general]](intro.multithread.general)
[1](#intro.multithread.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6564)
A [*thread of execution*](#def:thread_of_execution "6.10.2.1General[intro.multithread.general]") (also known as a [*thread*](#def:thread "6.10.2.1General[intro.multithread.general]")) is a single flow of
control within a program, including the initial invocation of a specific
top-level function, and recursively including every function invocation
subsequently executed by the thread[.](#intro.multithread.general-1.sentence-1)
[*Note [1](#intro.multithread.general-note-1)*:
When one thread creates another,
the initial call to the top-level function of the new thread is executed by the
new thread, not by the creating thread[.](#intro.multithread.general-1.sentence-2)
— *end note*]
Every thread in a program can
potentially use every object and function in a program[.](#intro.multithread.general-1.sentence-3)[37](#footnote-37 "An object with automatic or thread storage duration ([basic.stc]) is associated with one specific thread, and can be accessed by a different thread only indirectly through a pointer or reference ([basic.compound]).")
Under a hosted
implementation, a C++ program can have more than one thread running
concurrently[.](#intro.multithread.general-1.sentence-4)
The execution of each thread proceeds as defined by the remainder
of this document[.](#intro.multithread.general-1.sentence-5)
The execution of the entire program consists of an execution
of all of its threads[.](#intro.multithread.general-1.sentence-6)
[*Note [2](#intro.multithread.general-note-2)*:
Usually the execution can be viewed as an
interleaving of all its threads[.](#intro.multithread.general-1.sentence-7)
However, some kinds of atomic operations, for
example, allow executions inconsistent with a simple interleaving, as described
below[.](#intro.multithread.general-1.sentence-8)
— *end note*]
Under a freestanding implementation, it is implementation-defined whether a program can
have more than one thread of execution[.](#intro.multithread.general-1.sentence-9)
[2](#intro.multithread.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6600)
For a signal handler that is not executed as a result of a call to thestd::raise function, it is unspecified which thread of execution
contains the signal handler invocation[.](#intro.multithread.general-2.sentence-1)
[37)](#footnote-37)[37)](#footnoteref-37)
An object
with automatic or thread storage duration ([[basic.stc]](basic.stc "6.8.6Storage duration")) is associated with
one specific thread, and can be accessed by a different thread only indirectly
through a pointer or reference ([[basic.compound]](basic.compound "6.9.4Compound types"))[.](#footnote-37.sentence-1)
#### [6.10.2.2](#intro.races) Data races [[intro.races]](intro.races)
[1](#intro.races-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6607)
The value of an object visible to a thread T at a particular point is the
initial value of the object, a value assigned to the object by T, or a
value assigned to the object by another thread, according to the rules below[.](#intro.races-1.sentence-1)
[*Note [1](#intro.races-note-1)*:
In some cases, there might instead be undefined behavior[.](#intro.races-1.sentence-2)
Much of this
subclause is motivated by the desire to support atomic operations with explicit
and detailed visibility constraints[.](#intro.races-1.sentence-3)
However, it also implicitly supports a
simpler view for more restricted programs[.](#intro.races-1.sentence-4)
— *end note*]
[2](#intro.races-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6618)
Two expression evaluations [*conflict*](#def:conflict "6.10.2.2Data races[intro.races]") if one of them
- [(2.1)](#intro.races-2.1)
modifies ([[defns.access]](defns.access "3.1access")) a memory location ([[intro.memory]](intro.memory "6.8.1Memory model")) or
- [(2.2)](#intro.races-2.2)
starts or ends the lifetime of an object in a memory location
and the other one
- [(2.3)](#intro.races-2.3)
reads or modifies the same memory location or
- [(2.4)](#intro.races-2.4)
starts or ends the lifetime of an object occupying storage that
overlaps with the memory location[.](#intro.races-2.sentence-1)
[*Note [2](#intro.races-note-2)*:
A modification can still conflict
even if it does not alter the value of any bits[.](#intro.races-2.sentence-2)
— *end note*]
[3](#intro.races-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6639)
The library defines a number of atomic operations ([[atomics]](atomics "32.5Atomic operations")) and
operations on mutexes ([[thread]](thread "32Concurrency support library")) that are specially identified as
synchronization operations[.](#intro.races-3.sentence-1)
These operations play a special role in making
assignments in one thread visible to another[.](#intro.races-3.sentence-2)
A synchronization operation on one
or more memory locations is either an acquire operation, a
release operation, or both an acquire and release operation[.](#intro.races-3.sentence-3)
A synchronization
operation without an associated memory location is a fence and can be either an
acquire fence, a release fence, or both an acquire and release fence[.](#intro.races-3.sentence-4)
In
addition, there are relaxed atomic operations, which are not synchronization
operations, and atomic read-modify-write operations, which have special
characteristics[.](#intro.races-3.sentence-5)
[*Note [3](#intro.races-note-3)*:
For example, a call that acquires a mutex will
perform an acquire operation on the locations comprising the mutex[.](#intro.races-3.sentence-6)
Correspondingly, a call that releases the same mutex will perform a release
operation on those same locations[.](#intro.races-3.sentence-7)
Informally, performing a release operation onA forces priorside effects on other memory locations to become visible
to other threads that later perform a consume or an acquire operation onA[.](#intro.races-3.sentence-8)
“Relaxed” atomic operations are not synchronization operations even
though, like synchronization operations, they cannot contribute to data races[.](#intro.races-3.sentence-9)
— *end note*]
[4](#intro.races-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6664)
All modifications to a particular atomic object M occur in some
particular total order, called the [*modification order*](#def:modification_order "6.10.2.2Data races[intro.races]") of M[.](#intro.races-4.sentence-1)
[*Note [4](#intro.races-note-4)*:
There is a separate order for each
atomic object[.](#intro.races-4.sentence-2)
There is no requirement that these can be combined into a single
total order for all objects[.](#intro.races-4.sentence-3)
In general this will be impossible since different
threads can observe modifications to different objects in inconsistent orders[.](#intro.races-4.sentence-4)
— *end note*]
[5](#intro.races-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6674)
A [*release sequence*](#def:release_sequence "6.10.2.2Data races[intro.races]") headed
by a release operation A on an atomic object M is a maximal contiguous sub-sequence ofside effects in the modification order of M,
where the first operation is A, and
every subsequent operation is an atomic read-modify-write operation[.](#intro.races-5.sentence-1)
[6](#intro.races-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6683)
Certain library calls [*synchronize with*](#def:synchronize_with "6.10.2.2Data races[intro.races]") other library calls performed by
another thread[.](#intro.races-6.sentence-1)
For example, an atomic store-release synchronizes with a
load-acquire that takes its value from the store ([[atomics.order]](atomics.order "32.5.4Order and consistency"))[.](#intro.races-6.sentence-2)
[*Note [5](#intro.races-note-5)*:
Except in the specified cases, reading a later value does not
necessarily ensure visibility as described below[.](#intro.races-6.sentence-3)
Such a requirement would
sometimes interfere with efficient implementation[.](#intro.races-6.sentence-4)
— *end note*]
[*Note [6](#intro.races-note-6)*:
The
specifications of the synchronization operations define when one reads the value
written by another[.](#intro.races-6.sentence-5)
For atomic objects, the definition is clear[.](#intro.races-6.sentence-6)
All operations
on a given mutex occur in a single total order[.](#intro.races-6.sentence-7)
Each mutex acquisition “reads
the value written” by the last mutex release[.](#intro.races-6.sentence-8)
— *end note*]
[7](#intro.races-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6700)
An evaluation A [*happens before*](#def:happens_before "6.10.2.2Data races[intro.races]") an evaluation B (or, equivalently, B happens after A)
if either
- [(7.1)](#intro.races-7.1)
A is sequenced before B, or
- [(7.2)](#intro.races-7.2)
A synchronizes with B, or
- [(7.3)](#intro.races-7.3)
A happens before X and X happens before B[.](#intro.races-7.sentence-1)
[*Note [7](#intro.races-note-7)*:
An evaluation does not happen before itself[.](#intro.races-7.sentence-2)
— *end note*]
[8](#intro.races-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6713)
An evaluation A [*strongly happens before*](#def:strongly_happens_before "6.10.2.2Data races[intro.races]") an evaluation D if, either
- [(8.1)](#intro.races-8.1)
A is sequenced before D, or
- [(8.2)](#intro.races-8.2)
A synchronizes with D, and
both A and D are
sequentially consistent atomic operations ([[atomics.order]](atomics.order "32.5.4Order and consistency")), or
- [(8.3)](#intro.races-8.3)
there are evaluations B and C such that A is sequenced before B,B happens before C, andC is sequenced before D, or
- [(8.4)](#intro.races-8.4)
there is an evaluation B such thatA strongly happens before B, andB strongly happens before D[.](#intro.races-8.sentence-1)
[*Note [8](#intro.races-note-8)*:
Informally, if A strongly happens before B,
then A appears to be evaluated before B in all contexts[.](#intro.races-8.sentence-2)
— *end note*]
[9](#intro.races-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6735)
A [*visible side effect*](#def:side_effects,visible "6.10.2.2Data races[intro.races]") A on a scalar object or bit-field M with respect to a value computation B of M satisfies the
conditions:
- [(9.1)](#intro.races-9.1)
A happens before B and
- [(9.2)](#intro.races-9.2)
there is no otherside effect X to M such that A happens before X and X happens before B[.](#intro.races-9.sentence-1)
The value of a non-atomic scalar object or bit-field M, as determined by
evaluation B, is the value stored by thevisible side effect A[.](#intro.races-9.sentence-2)
[*Note [9](#intro.races-note-9)*:
If there is ambiguity about which side effect to a
non-atomic object or bit-field is visible, then the behavior is either
unspecified or undefined[.](#intro.races-9.sentence-3)
— *end note*]
[*Note [10](#intro.races-note-10)*:
This states that operations on
ordinary objects are not visibly reordered[.](#intro.races-9.sentence-4)
This is not actually detectable
without data races, but is needed to ensure that data races, as defined
below, and with suitable restrictions on the use of atomics, correspond to data
races in a simple interleaved (sequentially consistent) execution[.](#intro.races-9.sentence-5)
— *end note*]
[10](#intro.races-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6764)
The value of an
atomic object M, as determined by evaluation B, is the value
stored by some unspecified
side effect A that modifies M, where B does not happen
before A[.](#intro.races-10.sentence-1)
[*Note [11](#intro.races-note-11)*:
The set of such side effects is also restricted by the rest of the rules
described here, and in particular, by the coherence requirements below[.](#intro.races-10.sentence-2)
— *end note*]
[11](#intro.races-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6775)
If an operation A that modifies an atomic object M happens before
an operation B that modifies M, then A is earlier
than B in the modification order of M[.](#intro.races-11.sentence-1)
[*Note [12](#intro.races-note-12)*:
This requirement is known as write-write coherence[.](#intro.races-11.sentence-2)
— *end note*]
[12](#intro.races-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6784)
If avalue computation A of an atomic object M happens before a
value computation B of M, and A takes its value from a side
effect X on M, then the value computed by B is either
the value stored by X or the value stored by aside effect Y on M,
where Y follows X in the modification order of M[.](#intro.races-12.sentence-1)
[*Note [13](#intro.races-note-13)*:
This requirement is known as read-read coherence[.](#intro.races-12.sentence-2)
— *end note*]
[13](#intro.races-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6799)
If avalue computation A of an atomic object M happens before an
operation B that modifies M, then A takes its value from a side
effect X on M, where X precedes B in the
modification order of M[.](#intro.races-13.sentence-1)
[*Note [14](#intro.races-note-14)*:
This requirement is known as
read-write coherence[.](#intro.races-13.sentence-2)
— *end note*]
[14](#intro.races-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6812)
If aside effect X on an atomic object M happens before a value
computation B of M, then the evaluation B takes its
value from X or from aside effect Y that follows X in the modification order of M[.](#intro.races-14.sentence-1)
[*Note [15](#intro.races-note-15)*:
This requirement is known as write-read coherence[.](#intro.races-14.sentence-2)
— *end note*]
[15](#intro.races-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6825)
[*Note [16](#intro.races-note-16)*:
The four preceding coherence requirements effectively disallow
compiler reordering of atomic operations to a single object, even if both
operations are relaxed loads[.](#intro.races-15.sentence-1)
This effectively makes the cache coherence
guarantee provided by most hardware available to C++ atomic operations[.](#intro.races-15.sentence-2)
— *end note*]
[16](#intro.races-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6833)
[*Note [17](#intro.races-note-17)*:
The value observed by a load of an atomic depends on the “happens
before” relation, which depends on the values observed by loads of atomics[.](#intro.races-16.sentence-1)
The intended reading is that there must exist an
association of atomic loads with modifications they observe that, together with
suitably chosen modification orders and the “happens before” relation derived
as described above, satisfy the resulting constraints as imposed here[.](#intro.races-16.sentence-2)
— *end note*]
[17](#intro.races-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6843)
Two actions are [*potentially concurrent*](#def:potentially_concurrent "6.10.2.2Data races[intro.races]") if
- [(17.1)](#intro.races-17.1)
they are performed by different threads, or
- [(17.2)](#intro.races-17.2)
they are unsequenced, at least one is performed by a signal handler, and
they are not both performed by the same signal handler invocation[.](#intro.races-17.sentence-1)
The execution of a program contains a [*data race*](#def:data_race "6.10.2.2Data races[intro.races]") if it contains two
potentially concurrent conflicting actions, at least one of which is not atomic,
and neither happens before the other,
except for the special case for signal handlers described below[.](#intro.races-17.sentence-2)
Any such data race results in undefined
behavior[.](#intro.races-17.sentence-3)
[*Note [18](#intro.races-note-18)*:
It can be shown that programs that correctly use mutexes
and memory_order::seq_cst operations to prevent all data races and use no
other synchronization operations behave as if the operations executed by their
constituent threads were simply interleaved, with eachvalue computation of an
object being taken from the lastside effect on that object in that
interleaving[.](#intro.races-17.sentence-4)
This is normally referred to as “sequential consistency”[.](#intro.races-17.sentence-5)
However, this applies only to data-race-free programs, and data-race-free
programs cannot observe most program transformations that do not change
single-threaded program semantics[.](#intro.races-17.sentence-6)
In fact, most single-threaded program
transformations remain possible, since any program that behaves
differently as a result has undefined behavior[.](#intro.races-17.sentence-7)
— *end note*]
[18](#intro.races-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6874)
Two accesses to the same non-bit-field object
of type volatile std::sig_atomic_t do not
result in a data race if both occur in the same thread, even if one or more
occurs in a signal handler[.](#intro.races-18.sentence-1)
For each signal handler invocation, evaluations
performed by the thread invoking a signal handler can be divided into two
groups A and B, such that no evaluations inB happen before evaluations in A, and the
evaluations of such volatile std::sig_atomic_t objects take values as though
all evaluations in A happened before the execution of the signal
handler and the execution of the signal handler happened before all evaluations
in B[.](#intro.races-18.sentence-2)
[19](#intro.races-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6887)
[*Note [19](#intro.races-note-19)*:
Compiler transformations that introduce assignments to a potentially
shared memory location that would not be modified by the abstract machine are
generally precluded by this document, since such an assignment might overwrite
another assignment by a different thread in cases in which an abstract machine
execution would not have encountered a data race[.](#intro.races-19.sentence-1)
This includes implementations
of data member assignment that overwrite adjacent members in separate memory
locations[.](#intro.races-19.sentence-2)
Reordering of atomic loads in cases in which the atomics in question
might alias is also generally precluded, since this could violate the coherence
rules[.](#intro.races-19.sentence-3)
— *end note*]
[20](#intro.races-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6900)
[*Note [20](#intro.races-note-20)*:
It is possible that transformations that introduce a speculative read of a potentially
shared memory location do not preserve the semantics of the C++ program as
defined in this document, since they potentially introduce a data race[.](#intro.races-20.sentence-1)
However,
they are typically valid in the context of an optimizing compiler that targets a
specific machine with well-defined semantics for data races[.](#intro.races-20.sentence-2)
They would be
invalid for a hypothetical machine that is not tolerant of races or provides
hardware race detection[.](#intro.races-20.sentence-3)
— *end note*]
#### [6.10.2.3](#intro.progress) Forward progress [[intro.progress]](intro.progress)
[1](#intro.progress-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6913)
The implementation may assume that any thread will eventually do one of the
following:
- [(1.1)](#intro.progress-1.1)
terminate,
- [(1.2)](#intro.progress-1.2)
invoke the function std::this_thread::yield ([[thread.thread.this]](thread.thread.this "32.4.5Namespace this_­thread")),
- [(1.3)](#intro.progress-1.3)
make a call to a library I/O function,
- [(1.4)](#intro.progress-1.4)
perform an access through a volatile glvalue,
- [(1.5)](#intro.progress-1.5)
perform an atomic or synchronization operation
other than an atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency")), or
- [(1.6)](#intro.progress-1.6)
continue execution of a trivial infinite loop ([[stmt.iter.general]](stmt.iter.general "8.6.1General"))[.](#intro.progress-1.sentence-1)
[*Note [1](#intro.progress-note-1)*:
This is intended to allow compiler transformations
such as removal, merging, and reordering of empty loops,
even when termination cannot be proven[.](#intro.progress-1.sentence-2)
An affordance is made for trivial infinite loops,
which cannot be removed nor reordered[.](#intro.progress-1.sentence-3)
— *end note*]
[2](#intro.progress-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6933)
Executions of atomic functions
that are either defined to be lock-free ([[atomics.flag]](atomics.flag "32.5.10Flag type and operations"))
or indicated as lock-free ([[atomics.lockfree]](atomics.lockfree "32.5.5Lock-free property"))
are [*lock-free executions*](#def:lock-free_execution "6.10.2.3Forward progress[intro.progress]")[.](#intro.progress-2.sentence-1)
- [(2.1)](#intro.progress-2.1)
If there is only one thread that is not blocked ([[defns.block]](defns.block "3.6block"))
in a standard library function,
a lock-free execution in that thread shall complete[.](#intro.progress-2.1.sentence-1)
[*Note [2](#intro.progress-note-2)*:
Concurrently executing threads
might prevent progress of a lock-free execution[.](#intro.progress-2.1.sentence-2)
For example,
this situation can occur
with load-locked store-conditional implementations[.](#intro.progress-2.1.sentence-3)
This property is sometimes termed obstruction-free[.](#intro.progress-2.1.sentence-4)
— *end note*]
- [(2.2)](#intro.progress-2.2)
When one or more lock-free executions run concurrently,
at least one should complete[.](#intro.progress-2.2.sentence-1)
[*Note [3](#intro.progress-note-3)*:
It is difficult for some implementations
to provide absolute guarantees to this effect,
since repeated and particularly inopportune interference
from other threads
could prevent forward progress,
e.g.,
by repeatedly stealing a cache line
for unrelated purposes
between load-locked and store-conditional instructions[.](#intro.progress-2.2.sentence-2)
For implementations that follow this recommendation and
ensure that such effects cannot indefinitely delay progress
under expected operating conditions,
such anomalies
can therefore safely be ignored by programmers[.](#intro.progress-2.2.sentence-3)
Outside this document,
this property is sometimes termed lock-free[.](#intro.progress-2.2.sentence-4)
— *end note*]
[3](#intro.progress-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6974)
During the execution of a thread of execution, each of the following is termed
an [*execution step*](#def:execution_step "6.10.2.3Forward progress[intro.progress]"):
- [(3.1)](#intro.progress-3.1)
termination of the thread of execution,
- [(3.2)](#intro.progress-3.2)
performing an access through a volatile glvalue,
- [(3.3)](#intro.progress-3.3)
completion of a call to a library I/O function, or
- [(3.4)](#intro.progress-3.4)
completion of an atomic or synchronization operation
other than an atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4Order and consistency"))[.](#intro.progress-3.sentence-1)
[4](#intro.progress-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6985)
An invocation of a standard library function that blocks ([[defns.block]](defns.block "3.6block"))
is considered to continuously execute execution steps while waiting for the
condition that it blocks on to be satisfied[.](#intro.progress-4.sentence-1)
[*Example [1](#intro.progress-example-1)*:
A library I/O function that blocks until the I/O operation is complete can
be considered to continuously check whether the operation is complete[.](#intro.progress-4.sentence-2)
Each
such check consists of one or more execution steps, for example using
observable behavior of the abstract machine[.](#intro.progress-4.sentence-3)
— *end example*]
[5](#intro.progress-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6996)
[*Note [4](#intro.progress-note-4)*:
Because of this and the preceding requirement regarding what threads of execution
have to perform eventually, it follows that no thread of execution can execute
forever without an execution step occurring[.](#intro.progress-5.sentence-1)
— *end note*]
[6](#intro.progress-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7003)
A thread of execution [*makes progress*](#def:make_progress,thread "6.10.2.3Forward progress[intro.progress]") when an execution step occurs or a
lock-free execution does not complete because there are other concurrent threads
that are not blocked in a standard library function (see above)[.](#intro.progress-6.sentence-1)
[7](#intro.progress-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7009)
For a thread of execution providing [*concurrent forward progress guarantees*](#def:concurrent_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"),
the implementation ensures that the thread will eventually make progress for as
long as it has not terminated[.](#intro.progress-7.sentence-1)
[*Note [5](#intro.progress-note-5)*:
This applies regardless of whether or not other threads of execution (if any)
have been or are making progress[.](#intro.progress-7.sentence-2)
To eventually fulfill this requirement means that
this will happen in an unspecified but finite amount of time[.](#intro.progress-7.sentence-3)
— *end note*]
[8](#intro.progress-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7020)
It is implementation-defined whether the
implementation-created thread of execution that executesmain ([[basic.start.main]](#basic.start.main "6.10.3.1main function")) and the threads of execution created bystd::thread ([[thread.thread.class]](thread.thread.class "32.4.3Class thread"))
or std::jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4Class jthread"))
provide concurrent forward progress guarantees[.](#intro.progress-8.sentence-1)
General-purpose implementations should provide these guarantees[.](#intro.progress-8.sentence-2)
[9](#intro.progress-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7030)
For a thread of execution providing [*parallel forward progress guarantees*](#def:parallel_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"),
the implementation is not required to ensure that the thread will eventually make
progress if it has not yet executed any execution step; once this thread has
executed a step, it provides concurrent forward progress guarantees[.](#intro.progress-9.sentence-1)
[10](#intro.progress-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7037)
[*Note [6](#intro.progress-note-6)*:
This does not specify a requirement for when to start this thread of execution,
which will typically be specified by the entity that creates this thread of
execution[.](#intro.progress-10.sentence-1)
For example, a thread of execution that provides concurrent forward
progress guarantees and executes tasks from a set of tasks in an arbitrary order,
one after the other, satisfies the requirements of parallel forward progress for
these tasks[.](#intro.progress-10.sentence-2)
— *end note*]
[11](#intro.progress-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7047)
For a thread of execution providing [*weakly parallel forward progress
guarantees*](#def:weakly_parallel_forward_progress_guarantees "6.10.2.3Forward progress[intro.progress]"), the implementation does not ensure that the thread will eventually
make progress[.](#intro.progress-11.sentence-1)
[12](#intro.progress-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7053)
[*Note [7](#intro.progress-note-7)*:
Threads of execution providing weakly parallel forward progress guarantees cannot
be expected to make progress regardless of whether other threads make progress or
not; however, blocking with forward progress guarantee delegation, as defined below,
can be used to ensure that such threads of execution make progress eventually[.](#intro.progress-12.sentence-1)
— *end note*]
[13](#intro.progress-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7061)
Concurrent forward progress guarantees are stronger than parallel forward progress
guarantees, which in turn are stronger than weakly parallel forward progress
guarantees[.](#intro.progress-13.sentence-1)
[*Note [8](#intro.progress-note-8)*:
For example, some kinds of synchronization between threads of execution might only
make progress if the respective threads of execution provide parallel forward progress
guarantees, but will fail to make progress under weakly parallel guarantees[.](#intro.progress-13.sentence-2)
— *end note*]
[14](#intro.progress-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7071)
When a thread of execution P is specified to[*block with forward progress guarantee delegation*](#def:block_(execution),with_forward_progress_guarantee_delegation "6.10.2.3Forward progress[intro.progress]") on the completion of a set S of threads of execution,
then throughout the whole time of P being blocked on S,
the implementation shall ensure that the forward progress guarantees
provided by at least one thread of execution in S is at least as strong as P's forward progress guarantees[.](#intro.progress-14.sentence-1)
[*Note [9](#intro.progress-note-9)*:
It is unspecified which thread or threads of execution in S are chosen
and for which number of execution steps[.](#intro.progress-14.sentence-2)
The strengthening is not permanent and
not necessarily in place for the rest of the lifetime of the affected thread of
execution[.](#intro.progress-14.sentence-3)
As long as P is blocked, the implementation has to eventually
select and potentially strengthen a thread of execution in S[.](#intro.progress-14.sentence-4)
— *end note*]
Once a thread of execution in S terminates, it is removed from S[.](#intro.progress-14.sentence-5)
Once S is empty, P is unblocked[.](#intro.progress-14.sentence-6)
[15](#intro.progress-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7091)
[*Note [10](#intro.progress-note-10)*:
A thread of execution B thus can temporarily provide an effectively
stronger forward progress guarantee for a certain amount of time, due to a
second thread of execution A being blocked on it with forward
progress guarantee delegation[.](#intro.progress-15.sentence-1)
In turn, if B then blocks with
forward progress guarantee delegation on C, this can also temporarily
provide a stronger forward progress guarantee to C[.](#intro.progress-15.sentence-2)
— *end note*]
[16](#intro.progress-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7101)
[*Note [11](#intro.progress-note-11)*:
If all threads of execution in S finish executing (e.g., they terminate
and do not use blocking synchronization incorrectly), then P's execution
of the operation that blocks with forward progress guarantee delegation will not
result in P's progress guarantee being effectively weakened[.](#intro.progress-16.sentence-1)
— *end note*]
[17](#intro.progress-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7109)
[*Note [12](#intro.progress-note-12)*:
This does not remove any constraints regarding blocking synchronization for
threads of execution providing parallel or weakly parallel forward progress
guarantees because the implementation is not required to strengthen a particular
thread of execution whose too-weak progress guarantee is preventing overall progress[.](#intro.progress-17.sentence-1)
— *end note*]
[18](#intro.progress-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7117)
An implementation should ensure that the last value (in modification order)
assigned by an atomic or synchronization operation will become visible to all
other threads in a finite period of time[.](#intro.progress-18.sentence-1)
### [6.10.3](#basic.start) Start and termination [[basic.start]](basic.start)
#### [6.10.3.1](#basic.start.main) main function [[basic.start.main]](basic.start.main)
[1](#basic.start.main-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7129)
A program shall contain exactly one function called main that belongs to the global scope[.](#basic.start.main-1.sentence-1)
Executing a program starts a main thread of execution ([[intro.multithread]](#intro.multithread "6.10.2Multi-threaded executions and data races"), [[thread.threads]](thread.threads "32.4Threads"))
in which the main function is invoked[.](#basic.start.main-1.sentence-2)
It is implementation-defined
whether a program in a freestanding environment is required to define a main function[.](#basic.start.main-1.sentence-3)
[*Note [1](#basic.start.main-note-1)*:
In a freestanding environment, startup and termination isimplementation-defined; startup contains the
execution of constructors for non-local objects with static storage duration;
termination contains the execution of destructors for objects with static storage
duration[.](#basic.start.main-1.sentence-4)
— *end note*]
[2](#basic.start.main-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7147)
An implementation shall not predefine the main function[.](#basic.start.main-2.sentence-1)
Its type shall have C++ language linkage
and it shall have a declared return type of typeint, but otherwise its type is implementation-defined[.](#basic.start.main-2.sentence-2)
An implementation shall allow both
- [(2.1)](#basic.start.main-2.1)
a function of () returning int and
- [(2.2)](#basic.start.main-2.2)
a function of (int, pointer to pointer to char) returning int
as the type of main ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#basic.start.main-2.sentence-3)
In the latter form, for purposes of exposition, the first function
parameter is called argc and the second function parameter is
called argv, where argc shall be the number of
arguments passed to the program from the environment in which the
program is run[.](#basic.start.main-2.sentence-4)
Ifargc is nonzero these arguments shall be supplied inargv[0] through argv[argc - 1] as pointers to the initial
characters of null-terminated multibyte strings (ntmbss) ([[multibyte.strings]](multibyte.strings "16.3.3.3.4.3Multibyte strings"))
and argv[0] shall be the pointer to
the initial character of an ntmbs that represents the name used to
invoke the program or ""[.](#basic.start.main-2.sentence-5)
The value of argc shall be
non-negative[.](#basic.start.main-2.sentence-6)
The value of argv[argc] shall be 0[.](#basic.start.main-2.sentence-7)
*Recommended practice*: Any further (optional) parameters should be added after argv[.](#basic.start.main-2.sentence-8)
[3](#basic.start.main-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7179)
The function main shall not be named by an expression[.](#basic.start.main-3.sentence-1)
The linkage ([[basic.link]](basic.link "6.7Program and linkage")) of main isimplementation-defined[.](#basic.start.main-3.sentence-2)
A program that defines main as
deleted or that declares main to beinline, static, constexpr, or consteval is ill-formed[.](#basic.start.main-3.sentence-3)
The function main shall not be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))[.](#basic.start.main-3.sentence-4)
The main function shall not be declared with a[*linkage-specification*](dcl.link#nt:linkage-specification "9.12Linkage specifications[dcl.link]") ([[dcl.link]](dcl.link "9.12Linkage specifications")) other than "C++"[.](#basic.start.main-3.sentence-5)
A program that declares
- [(3.1)](#basic.start.main-3.1)
a variable main that belongs to the global scope, or
- [(3.2)](#basic.start.main-3.2)
a function main that belongs to the global scope and
is attached to a named module, or
- [(3.3)](#basic.start.main-3.3)
a function template main that belongs to the global scope, or
- [(3.4)](#basic.start.main-3.4)
an entity named main with C language linkage (in any namespace)
is ill-formed[.](#basic.start.main-3.sentence-6)
The name main is
not otherwise reserved[.](#basic.start.main-3.sentence-7)
[*Example [1](#basic.start.main-example-1)*:
Member functions, classes, and
enumerations can be called main, as can entities in other
namespaces[.](#basic.start.main-3.sentence-8)
— *end example*]
[4](#basic.start.main-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7211)
Terminating the program
without leaving the current block (e.g., by calling the functionstd::exit(int) ([[support.start.term]](support.start.term "17.5Startup and termination"))) does not destroy any
objects with automatic storage duration ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#basic.start.main-4.sentence-1)
Ifstd::exit is invoked during the destruction of
an object with static or thread storage duration, the program has undefined
behavior[.](#basic.start.main-4.sentence-2)
[5](#basic.start.main-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7223)
A return statement ([[stmt.return]](stmt.return "8.8.4The return statement")) in main has the effect of leaving the main function (destroying any objects with automatic storage duration
and evaluating any postcondition assertions of main)
and calling std::exit with the return value as the argument[.](#basic.start.main-5.sentence-1)
If control flows off the end of
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of main,
the effect is equivalent to a return with operand 0 (see also [[except.handle]](except.handle "14.4Handling an exception"))[.](#basic.start.main-5.sentence-2)
#### [6.10.3.2](#basic.start.static) Static initialization [[basic.start.static]](basic.start.static)
[1](#basic.start.static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7238)
Variables with static storage duration
are initialized as a consequence of program initiation[.](#basic.start.static-1.sentence-1)
Variables with
thread storage duration are initialized as a consequence of thread execution[.](#basic.start.static-1.sentence-2)
Within each of these phases of initiation, initialization occurs as follows[.](#basic.start.static-1.sentence-3)
[2](#basic.start.static-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7246)
[*Constant initialization*](#def:constant_initialization "6.10.3.2Static initialization[basic.start.static]") is performed
if a variable with static or thread storage duration
is constant-initialized ([[expr.const]](expr.const "7.7Constant expressions"))[.](#basic.start.static-2.sentence-1)
If constant initialization is not performed, a variable with static
storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2Static storage duration")) or thread storage
duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3Thread storage duration")) is zero-initialized ([[dcl.init]](dcl.init "9.5Initializers"))[.](#basic.start.static-2.sentence-2)
Together, zero-initialization and constant initialization are called[*static initialization*](#def:initialization,static "6.10.3.2Static initialization[basic.start.static]");
all other initialization is [*dynamic initialization*](#def:initialization,dynamic "6.10.3.2Static initialization[basic.start.static]")[.](#basic.start.static-2.sentence-3)
All static initialization strongly happens before ([[intro.races]](#intro.races "6.10.2.2Data races"))
any dynamic initialization[.](#basic.start.static-2.sentence-4)
[*Note [1](#basic.start.static-note-1)*:
The dynamic initialization of non-block variables is described
in [[basic.start.dynamic]](#basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"); that of static block variables is described
in [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#basic.start.static-2.sentence-5)
— *end note*]
[3](#basic.start.static-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7266)
An implementation is permitted to perform the initialization of a
variable with static or thread storage duration as a static
initialization even if such initialization is not required to be done
statically, provided that
- [(3.1)](#basic.start.static-3.1)
the dynamic version of the initialization does not change the
value of any other object of static or thread storage duration
prior to its initialization, and
- [(3.2)](#basic.start.static-3.2)
the static version of the initialization produces the same value
in the initialized variable as would be produced by the dynamic
initialization if all variables not required to be initialized statically
were initialized dynamically[.](#basic.start.static-3.sentence-1)
[*Note [2](#basic.start.static-note-2)*:
As a consequence, if the initialization of an object obj1 refers to an
object obj2 potentially requiring dynamic initialization and defined
later in the same translation unit, it is unspecified whether the value of obj2 used
will be the value of the fully initialized obj2 (because obj2 was statically
initialized) or will be the value of obj2 merely zero-initialized[.](#basic.start.static-3.sentence-2)
For example,inline double fd() { return 1.0; }extern double d1;double d2 = d1; // unspecified:// either statically initialized to 0.0 or// dynamically initialized to 0.0 if d1 is// dynamically initialized, or 1.0 otherwisedouble d1 = fd(); // either initialized statically or dynamically to 1.0
— *end note*]
#### [6.10.3.3](#basic.start.dynamic) Dynamic initialization of non-block variables [[basic.start.dynamic]](basic.start.dynamic)
[1](#basic.start.dynamic-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7302)
Dynamic initialization of a non-block variable with static storage duration is
unordered if the variable is an implicitly or explicitly instantiated
specialization, is partially-ordered if the variable
is an inline variable that is not an implicitly or explicitly instantiated
specialization, and otherwise is ordered[.](#basic.start.dynamic-1.sentence-1)
[*Note [1](#basic.start.dynamic-note-1)*:
A non-inline explicit specialization of a templated variable
has ordered initialization[.](#basic.start.dynamic-1.sentence-2)
— *end note*]
[2](#basic.start.dynamic-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7316)
A declaration D is[*appearance-ordered*](#def:appearance-ordered "6.10.3.3Dynamic initialization of non-block variables[basic.start.dynamic]") before a declaration E if
- [(2.1)](#basic.start.dynamic-2.1)
D appears in the same translation unit as E, or
- [(2.2)](#basic.start.dynamic-2.2)
the translation unit containing E has an interface dependency on the translation unit containing D,
in either case prior to E[.](#basic.start.dynamic-2.sentence-1)
[3](#basic.start.dynamic-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7326)
Dynamic initialization of non-block variables V and W with static storage duration are ordered as follows:
- [(3.1)](#basic.start.dynamic-3.1)
If V and W have ordered initialization and
the definition of V is appearance-ordered before the definition of W, or
if V has partially-ordered initialization,W does not have unordered initialization, and
for every definition E of W there exists a definition D of V such that D is appearance-ordered before E, then
* [(3.1.1)](#basic.start.dynamic-3.1.1)
if the program does not start a thread ([[intro.multithread]](#intro.multithread "6.10.2Multi-threaded executions and data races"))
other than the main thread ([[basic.start.main]](#basic.start.main "6.10.3.1main function"))
or V and W have ordered initialization and
they are defined in the same translation unit,
the initialization of V is sequenced before
the initialization of W;
* [(3.1.2)](#basic.start.dynamic-3.1.2)
otherwise,
the initialization of V strongly happens before
the initialization of W[.](#basic.start.dynamic-3.1.sentence-1)
- [(3.2)](#basic.start.dynamic-3.2)
Otherwise, if the program starts a thread
other than the main thread
before either V or W is initialized,
it is unspecified in which threads
the initializations of V and W occur;
the initializations are unsequenced if they occur in the same thread[.](#basic.start.dynamic-3.2.sentence-1)
- [(3.3)](#basic.start.dynamic-3.3)
Otherwise, the initializations of V and W are indeterminately sequenced[.](#basic.start.dynamic-3.3.sentence-1)
[*Note [2](#basic.start.dynamic-note-2)*:
This definition permits initialization of a sequence of
ordered variables concurrently with another sequence[.](#basic.start.dynamic-3.sentence-2)
— *end note*]
[4](#basic.start.dynamic-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7371)
A [*non-initialization odr-use*](#def:odr-use,non-initialization "6.10.3.3Dynamic initialization of non-block variables[basic.start.dynamic]") is an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) not caused directly or indirectly by
the initialization of a non-block static or thread storage duration variable[.](#basic.start.dynamic-4.sentence-1)
[5](#basic.start.dynamic-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7377)
It is implementation-defined
whether the dynamic initialization of a
non-block non-inline variable with static storage duration
is sequenced before the first statement of main or is deferred[.](#basic.start.dynamic-5.sentence-1)
If it is deferred, it strongly happens before
any non-initialization odr-use
of any non-inline function or non-inline variable
defined in the same translation unit as the variable to be initialized[.](#basic.start.dynamic-5.sentence-2)[38](#footnote-38 "A non-block variable with static storage duration having initialization with side effects is initialized in this case, even if it is not itself odr-used ([term.odr.use], [basic.stc.static]).")
It is implementation-defined
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#basic.start.dynamic-5.sentence-3)
*Recommended practice*: An implementation should choose such points in a way
that allows the programmer to avoid deadlocks[.](#basic.start.dynamic-5.sentence-4)
[*Example [1](#basic.start.dynamic-example-1)*: // - File 1 -#include "a.h"#include "b.h" B b;
A::A() { b.Use();}// - File 2 -#include "a.h" A a;
// - File 3 -#include "a.h"#include "b.h"extern A a;extern B b;
int main() { a.Use();
b.Use();}
It is implementation-defined
whether either a or b is
initialized before main is entered or whether the
initializations are delayed until a is first odr-used inmain[.](#basic.start.dynamic-5.sentence-5)
In particular, if a is initialized beforemain is entered, it is not guaranteed that b will be
initialized before it is odr-used by the initialization of a, that
is, before A::A is called[.](#basic.start.dynamic-5.sentence-6)
If, however, a is initialized
at some point after the first statement of main, b will
be initialized prior to its use in A::A[.](#basic.start.dynamic-5.sentence-7)
— *end example*]
[6](#basic.start.dynamic-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7437)
It is implementation-defined
whether the dynamic initialization of a
non-block inline variable with static storage duration
is sequenced before the first statement of main or is deferred[.](#basic.start.dynamic-6.sentence-1)
If it is deferred, it strongly happens before
any non-initialization odr-use
of that variable[.](#basic.start.dynamic-6.sentence-2)
It is implementation-defined
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#basic.start.dynamic-6.sentence-3)
[7](#basic.start.dynamic-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7448)
It is implementation-defined
whether the dynamic initialization of a
non-block non-inline variable with thread storage duration
is sequenced before the first statement of the initial function of a thread or is deferred[.](#basic.start.dynamic-7.sentence-1)
If it is deferred,
the initialization associated with the entity for thread *t* is sequenced before the first non-initialization odr-use by *t* of any non-inline variable with thread storage duration
defined in the same translation unit as the variable to be initialized[.](#basic.start.dynamic-7.sentence-2)
It is implementation-defined
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#basic.start.dynamic-7.sentence-3)
[8](#basic.start.dynamic-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7461)
If the initialization of
a non-block variable with static or thread storage duration
exits via an exception,
the function std::terminate is called ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#basic.start.dynamic-8.sentence-1)
[38)](#footnote-38)[38)](#footnoteref-38)
A non-block variable with static storage duration
having initialization
with side effects is initialized in this case,
even if it is not itself odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule"), [[basic.stc.static]](basic.stc.static "6.8.6.2Static storage duration"))[.](#footnote-38.sentence-1)
#### [6.10.3.4](#basic.start.term) Termination [[basic.start.term]](basic.start.term)
[1](#basic.start.term-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7470)
Constructed objects ([[dcl.init]](dcl.init "9.5Initializers"))
with static storage duration are destroyed
and functions registered with std::atexit are called as part of a call tostd::exit ([[support.start.term]](support.start.term "17.5Startup and termination"))[.](#basic.start.term-1.sentence-1)
The call to std::exit is sequenced before
the destructions and the registered functions[.](#basic.start.term-1.sentence-2)
[*Note [1](#basic.start.term-note-1)*:
Returning from main invokes std::exit ([[basic.start.main]](#basic.start.main "6.10.3.1main function"))[.](#basic.start.term-1.sentence-3)
— *end note*]
[2](#basic.start.term-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7487)
Constructed objects with thread storage duration within a given thread
are destroyed as a result of returning from the initial function of that thread and as a
result of that thread calling std::exit[.](#basic.start.term-2.sentence-1)
The destruction of all constructed objects with thread storage
duration within that thread strongly happens before destroying
any object with static storage duration[.](#basic.start.term-2.sentence-2)
[3](#basic.start.term-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7495)
If the completion of the constructor or dynamic initialization of an object with static
storage duration strongly happens before that of another, the completion of the destructor
of the second is sequenced before the initiation of the destructor of the first[.](#basic.start.term-3.sentence-1)
If the completion of the constructor or dynamic initialization of an object with thread
storage duration is sequenced before that of another, the completion of the destructor
of the second is sequenced before the initiation of the destructor of the first[.](#basic.start.term-3.sentence-2)
If an object is
initialized statically, the object is destroyed in the same order as if
the object was dynamically initialized[.](#basic.start.term-3.sentence-3)
For an object of array or class
type, all subobjects of that object are destroyed before any block
variable with static storage duration initialized during the construction
of the subobjects is destroyed[.](#basic.start.term-3.sentence-4)
If the destruction of an object with static or thread storage duration
exits via an exception,
the function std::terminate is called ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#basic.start.term-3.sentence-5)
[4](#basic.start.term-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7512)
If a function contains a block variable of static or thread storage duration that has been
destroyed and the function is called during the destruction of an object with static or
thread storage duration, the program has undefined behavior if the flow of control
passes through the definition of the previously destroyed block variable[.](#basic.start.term-4.sentence-1)
[*Note [2](#basic.start.term-note-2)*:
Likewise, the behavior is undefined
if the block variable is used indirectly (e.g., through a pointer)
after its destruction[.](#basic.start.term-4.sentence-2)
— *end note*]
[5](#basic.start.term-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7523)
If the completion of the initialization of an object with static storage
duration strongly happens before a call to std::atexit (see[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2Header <cstdlib> synopsis[cstdlib.syn]"), [[support.start.term]](support.start.term "17.5Startup and termination")), the call to the function passed tostd::atexit is sequenced before the call to the destructor for the object[.](#basic.start.term-5.sentence-1)
If a
call to std::atexit strongly happens before the completion of the initialization of
an object with static storage duration, the call to the destructor for the
object is sequenced before the call to the function passed to std::atexit[.](#basic.start.term-5.sentence-2)
If a
call to std::atexit strongly happens before another call to std::atexit, the
call to the function passed to the second std::atexit call is sequenced before
the call to the function passed to the first std::atexit call[.](#basic.start.term-5.sentence-3)
[6](#basic.start.term-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7537)
If there is a use of a standard library object or function not permitted within signal
handlers ([[support.runtime]](support.runtime "17.14Other runtime support")) that does not happen before ([[intro.multithread]](#intro.multithread "6.10.2Multi-threaded executions and data races"))
completion of destruction of objects with static storage duration and execution ofstd::atexit registered functions ([[support.start.term]](support.start.term "17.5Startup and termination")), the program has
undefined behavior[.](#basic.start.term-6.sentence-1)
[*Note [3](#basic.start.term-note-3)*:
If there is a use of an object with static storage
duration that does not happen before the object's destruction, the program has undefined
behavior[.](#basic.start.term-6.sentence-2)
Terminating every thread before a call to std::exit or the exit frommain is sufficient, but not necessary, to satisfy these requirements[.](#basic.start.term-6.sentence-3)
These
requirements permit thread managers as static-storage-duration objects[.](#basic.start.term-6.sentence-4)
— *end note*]
[7](#basic.start.term-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7551)
Calling the function std::abort() declared in[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2Header <cstdlib> synopsis[cstdlib.syn]") terminates the program without executing any destructors
and without calling
the functions passed to std::atexit() or std::at_quick_exit()[.](#basic.start.term-7.sentence-1)