Title
Tracking of created and destroyed subobjects
Status
open
Section
14.3 [except.ctor]
Submitter
Richard Smith

Created on 2022-06-16.00:00:00 last changed 5 days ago

Messages

Date: 2022-06-21.15:36:47

Suggested resolution:

Change in 14.3 [except.ctor] paragraph 3 as follows:

If the initialization or destruction of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for each of the object's direct subobjects and, for a complete object, virtual base class subobjects that were directly initialized by the object's initialization and , whose initialization has completed (9.4 [dcl.init]) and whose destructor has not yet begun execution, except that in the case of destruction, the variant members of a union-like class are not destroyed. A subobject is directly initialized if its initialization is specified in 11.9.3 [class.base.init] for initialization by constructor, in 11.9.4 [class.inhctor.init] for initialization by inherited constructor, in 9.4.2 [dcl.init.aggr] for aggregate initialization, or in 9.4.1 [dcl.init.general] for default-initialization, value-initialization, or direct-initialization of an array. [Note: This includes virtual base class subobjects if the initialization is for a complete object, and can include variant members that were nominated explicitly by a mem-initializer or designated-initializer-clause or that have a default member initializer. -- end note]

If the destructor of an object is terminated by an exception, each destructor invocation that would be performed after executing the body of the destructor (11.4.7 [class.dtor]) and that has not yet begun execution is performed. [Note: This includes virtual base class subobjects if the destructor was invoked for a complete object. -- end note ]

Date: 2022-06-16.00:00:00

Subclause 14.3 [except.ctor] paragraph 3 specifies:

If the initialization or destruction of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for each of the object's direct subobjects and, for a complete object, virtual base class subobjects, whose initialization has completed (9.4 [dcl.init]) and whose destructor has not yet begun execution, except that in the case of destruction, the variant members of a union-like class are not destroyed.

A traditional implementation has no way of knowing which subobjects are in the state that their initialization has completed but their destructor has not yet begun execution. For example, the program might call the destructor explicitly, and the implementation does not track whether that has happened. The intent here is that it only matters whether the implied destructor call generated implicitly as part of the class object's destructor has begun yet, but it does not say that, and the reference to variant members reinforces the interpretation that the set of subobjects that are destroyed is determined dynamically based on which objects are within their lifetimes. Also, combining construction and destruction rules here confuses the matter further -- in "whose initialization has completed and whose destructor has not yet begun" we care exclusively about the first part in constructors and exclusively about the second part in destructors.

The set of things that we actually want to destroy here is the things that were initialized by the initialization (constructor or aggregate initializer) itself, not the things that have been constructed and not destroyed by evaluations that the initialization happens to perform. For example:

  struct A {
    union { T x; U y; };
    A() { throw "does not destroy x"; }
    A(int) : x() { throw "does destroy x"; }
    A(float) : x() { x.~T(); throw "still destroys x, oops"; }
    A(double) : x() {
      x.~T();
      new(&y) U();
      throw "destroys x, does not destroy y";
    }
  };

and similarly for aggregate initialization:

  struct B {
    union { T x; U y; };
    int a;
  };
  B b = { .x = {}, .a = (b.x.~T(), new (&b.y) U(), throw "destroys x not y")};

Destruction is completely different: we just want to destroy all the things that the destructor was going to destroy anyway and hasn't already started destroying.

History
Date User Action Args
2022-06-21 15:36:47adminsetmessages: + msg6862
2022-06-16 00:00:00admincreate