C++ Logo

STD-DISCUSSION

Advanced search

Subject: Re: About the description of [basic.life]/6
From: yo mizu (mizu2594_at_[hidden])
Date: 2020-04-14 06:51:12


I'm sorry to cut in on you, but I didn't understand why "pb" in the
example meets the requirements of [basic.life]/6.

On Fri, Apr 10, 2020 at 18:34 CDT Tadeus Prastowo via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> This is not UB, including the example's *pb, because:
> [basic.lval]/1.4 "An lvalue is a glvalue that is not an xvalue."
> [basic.life]/6 "Indirection through such a pointer is permitted but
> the resulting lvalue may only be used in limited ways, as described
> below."
> [basic.life]/7 "using the properties of the glvalue that do not depend
> on its value is well-defined"

The original example is as follows.

#include <cstdlib>

struct B {
  virtual void f();
  void mutate();
  virtual ~B();
};

struct D1 : B { void f(); };
struct D2 : B { void f(); };

void B::mutate() {
  new (this) D2; // reuses storage — ends the lifetime of *this
  f(); // undefined behavior
  ... = this; // OK, this points to valid memory
}

void g() {
  void* p = std::malloc(sizeof(D1) + sizeof(D2));
  B* pb = new (p) D1;
  pb->mutate();
  *pb; // OK: pb points to valid memory
  void* q = pb; // OK: pb points to valid memory
  pb->f(); // undefined behavior, lifetime of *pb has ended
}

Here is a simplified version.

#include <cstdlib>

struct B {
  virtual void f();
  virtual ~B();
};

struct D1 : B { void f(); };
struct D2 : B { void f(); };

void g() {
  void* p = std::malloc(sizeof(D1) + sizeof(D2));
  B* pb = new (p) D1;
  pb->~B();
  // At this point, pb represents the address of the storage location
where an object was located after the lifetime of the object has ended
and before the storage which the object occupied is reused or
released,
  // so pb meets the requirements of [basic.life]/6.

  new (pb) D2; // reuses storage
  // At this point, pb represents the address of the storage location
where an object was located after the lifetime of the object has ended
and after the storage which the object occupied is reused,
  // because a new object is created and reuses the storage,
  // so I think pb does not meet the requirements of [basic.life]/6.

  *pb;
  pb->f();
}

Thank you.


STD-DISCUSSION list run by std-discussion-owner@lists.isocpp.org

Older Archives on Google Groups