This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-31


2929. Lifetime of trivially-destructible static or thread-local objects

Section: 6.9.3.4  [basic.start.term]     Status: review     Submitter: Mathias Stearn     Date: 2024-08-05

Issue 2256 (adopted in February, 2019) changed the rules such that the lifetimes of objects do not depend on whether the destructor is trivial or not. However, the motivation of that issue mentioned only objects with automatic storage duration. To be able to avoid order-of-destruction issues across translation units, it would be useful to never end the lifetime of trivially-destructible objects with static storage duration and to delay the end of the lifetime of such objects with thread storage duration as long as possible.

Possible resolution [SUPERSEDED]:

  1. Change in 6.9.3.4 [basic.start.term] paragraph 1 as follows:

    Constructed class objects (9.4 [dcl.init]) with static storage duration and having a non-trivial destructor (11.4.7 [class.dtor]) are destroyed and functions registered with std::atexit are called as part of a call to std::exit (17.5 [support.start.term]). The call to std::exit is sequenced before the destructions and the registered functions.
  2. Change in 6.9.3.4 [basic.start.term] paragraph 2 as follows:

    Constructed class objects with thread storage duration within a given thread and having a non-trivial destructor (11.4.7 [class.dtor]) are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling std::exit. The destruction of all those constructed objects with thread storage duration within that thread strongly happens before releasing the storage for objects with thread storage duration within that thread, which in turn strongly happens before destroying any object with static storage duration.

CWG 2024-09-27

Also allow for constant destruction, consider arrays of class type, and adjust the happens-before requirements.

Proposed resolution (approved by CWG 2024-10-11) [SUPERSEDED]:

  1. Change in 6.9.3.4 [basic.start.term] paragraph 1 as follows:

    Constructed complete objects (9.4 [dcl.init]) with static storage duration and not having constant destruction (7.7 [expr.const]) are destroyed and functions registered with std::atexit are called as part of a call to std::exit (17.5 [support.start.term]). The call to std::exit is sequenced before the destructions and the registered functions.
  2. Change in 6.9.3.4 [basic.start.term] paragraph 2 as follows:

    Constructed complete objects with thread storage duration within a given thread and not having constant destruction (7.7 [expr.const]) are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling std::exit. The destruction of those constructed objects within that thread is sequenced before releasing the storage for all objects with thread storage duration within that thread (6.7.6.3 [basic.stc.thread]). Also, the The destruction of all those constructed objects with thread storage duration within that thread strongly happens before destroying any object with static storage duration.

CWG 2024-11-22

Continue to actually destroy constant-destruction objects, but do so after all dynamic destruction is done.

Proposed resolution:

  1. Change in 6.9.3.4 [basic.start.term] paragraph 1 as follows:

    Constructed complete objects (9.4 [dcl.init]) with static storage duration are destroyed and functions registered with std::atexit are called as part of a call to std::exit (17.5 [support.start.term]). The call to std::exit is sequenced before the destructions and the registered functions.
  2. Change in 6.9.3.4 [basic.start.term] paragraph 2 as follows:

    Constructed complete 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. The destruction of those constructed objects is sequenced before releasing the storage for any object with thread storage duration within that thread (6.7.6.3 [basic.stc.thread]). The The destruction of all those constructed objects with thread storage duration within that thread strongly happens before destroying any object with static storage duration.
  3. Add a paragraph after 6.9.3.4 [basic.start.term] paragraph 2:

    The destruction of an object with thread storage duration within a given thread and having constant destruction (7.7 [expr.const]) is sequenced after the destruction of any other object with thread storage duration within the thread. The destruction of an object with static storage duration and having constant destruction is sequenced after the destruction of any other object with static storage duration and after any call to a function passed to std::atexit. The sequencing rules in the remainder of this subclause apply only to objects not having constant destruction.
  4. Do not change in 6.9.3.4 [basic.start.term] paragraph 3:

    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. 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. If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized. 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. If the destruction of an object with static or thread storage duration exits via an exception, the function std::terminate is called (14.6.2 [except.terminate]).