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-19


2158. Polymorphic behavior during destruction

Section: 11.4.7  [class.dtor]     Status: drafting     Submitter: Richard Smith     Date: 2015-07-13

Consider the following example:

  #include <stdio.h>
  struct Base {
    Base *p;
    virtual void f() { puts("base"); }
    ~Base() {
      p->f();
    }
  };
  struct Derived : Base {
    Derived() { p = this; }
    void f() { puts("derived"); }
    void g() {
      p->f();
      delete this;
    }
  };
  void h() {
    Derived *p = new Derived;
    p->g();
  }

Should this have defined behavior? On the one hand, the Derived object is in its period of destruction, so the behavior of the p->f() call in the Base destructor should be to call Base::f(). On the other hand, p is a pointer to a Derived object whose lifetime has ended, and the rules in 6.7.4 [basic.life] don't appear to allow the call. (Calling this->f() from the Base destructor would be OK — the question is whether you can do that for a pointer that used to point to the derived object, or if you can only do it for a pointer that was “created” after the dynamic type of the object changed to be Base.)

If the above is valid, it has severe implications for devirtualization. The purpose of 6.7.4 [basic.life] paragraph 7 appears to be to allow an implementation to assume that if it will perform two loads of a constant field (for instance, a const member, the implicit pointer for a reference member, or a vptr), and the two loads are performed on the “same pointer value”, then they load the same value.

Should there be a rule for destructors similar to that of 11.4.5 [class.ctor] paragraph 12?

During the construction of a const object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this pointer, the value of the object or subobject thus obtained is unspecified.