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

2024-11-11


1530. Member access in out-of-lifetime objects

Section: 6.7.3  [basic.life]     Status: drafting     Submitter: Howard Hinnant     Date: 2012-07-26

According to 6.7.3 [basic.life] paragraphs 5 and 6, a program has undefined behavior if a pointer or glvalue designating an out-of-lifetime object

is used to access a non-static data member or call a non-static member function of the object

It is not clear what the word “access” means in this context. A reasonable interpretation might be using the pointer or glvalue as the left operand of a class member access expression; alternatively, it might mean to read or write the value of that member, allowing a class member access expression that is used only to form an address or bind a reference.

This needs to be clarified. A relevant consideration is the recent adoption of the resolution of issue 597, which eased the former restriction on simple address manipulations involving out-of-lifetime objects: if base-class offset calculations are now allowed, why not non-static data member offset calculations?

(See also issue 1531 for other uses of the term “access.”)

Additional note (January, 2013):

A related question is the meaning of the phrase “before the constructor begins execution” in 11.9.5 [class.cdtor] paragraph 1 means:

For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior.

For example:

  struct DerivedMember { ... };

  struct Base {
    Base(DerivedMember const&);
  };

  struct Derived : Base {
    DerivedMember x;
    Derived() : Base(x) {}
  };

  Derived a;

Is the reference to Derived::x in the mem-initializer valid?

Additional note (March, 2013):

This clause is phrased in terms of the execution of the constructor. However, it is possible for an aggregate to have a non-trivial default constructor and be initialized without executing a constructor. The wording needs to be updated to allow for non-constructor initialization to avoid appearing to imply undefined behavior for an example like:

  struct X {
    std::string s;
  } x = {};
  std::string t = x.s;  // No constructor called for x: undefined behavior?