Topic: Object Lifetime & Member Access


Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/11
Raw View
Dave Lorde <dlorde@cix.compulink.co.uk> writes:

>----------------  3.8  Object Lifetime ---------
>"1. The lifetime of an object of type T begins when:
>  --if T is a class type with a non-trivial constructor, the
>  constructor call has completed.
>
>"5. Before the lifetime of an object has started... any pointer that
>refers to the storage location where the object will be... may be used
>but only in limited  ways.
>
>"If the object will be or was of a non-POD class type, the program has
>undefined behavior if:
>--the pointer is used to access a non-static data  member or call a
>non-static member function of the object"

That is a bug in the DWP.  Paragraphs 5 and 6 in 3.8 are not
intended to apply during construction or during destruction.
Sections 12.6.2 [class.init] and 12.7 [class.cdtor] are intended
to cover those cases.

>The inescapable logic of basic.life (3.8) is that within the
>constructor, the result of accessing any non-static member data or
>function is undefined

Yes.  That was definitely not the intent, however.

>What is the position regarding access to member data after the
>initialiser list has completed, but before returning from the
>constructor? A literal reading of the standard suggests this is also
>undefined.

The intent was definitely that this should be well-defined.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Dave Lorde <dlorde@cix.compulink.co.uk>
Date: 1997/04/10
Raw View

In the April C++ Report, Josee Lajoie describes object lifetimes under
the CD2 C++ Standard paper, saying that a non POD object's lifetime
starts when it's constructor completes and ends when the destructor
starts (page 9).  OK, seems reasonable...

She goes on to describe Rule 4 of the object lifetime rules clarified
by the C++ standards committee, saying that before the lifetime of a
POD object starts (or after it ends), calling a member function results
in undefined behaviour. The restriction, previously for virtual
functions, now extends to *any* member function. The reason given is to
allow implementations to call non-virtual functions through indirect
means (function ptrs, etc.).

I double-checked CD2 C++ Standard paper, and came across the following
(relevant bits only):

----------------  3.8  Object Lifetime ---------
"1. The lifetime of an object of type T begins when:
  --if T is a class type with a non-trivial constructor, the
  constructor call has completed.

"5. Before the lifetime of an object has started... any pointer that
refers to the storage location where the object will be... may be used
but only in limited  ways.

"If the object will be or was of a non-POD class type, the program has
undefined behavior if:
--the pointer is used to access a non-static data  member or call a
non-static member function of the object"

*BUT*  class.cdtor (sec 12/7) still retains the expected behaviour:

----------------  12.7  Class Constructor/Destructor  ---------
"3 Member  functions,  including virtual functions (_class.virtual_),
can be called  during construction  or  destruction (_class.base.init_).
When  a  virtual function is called directly or indirectly from a
constructor (including from the mem-initializer for  a  data member)
or from  a  destructor,  and  the object to which the call applies is
the object under construction or destruction, the function called  is
the one  defined in the constructor or destructor's own class or in one
of its bases, but not a function overriding it in a class derived  from
the  constructor or destructor's class, or overriding it in one of the
other base classes of the most derived object  (_intro.object_).   If
the  virtual  function  call  uses  an explicit class  member access
(_expr.ref_) and the object-expression refers to the object under
construction or  destruction  but its type is neither the constructor
or destructor's own class or one of its bases, the result of the call
is undefined."

-------------------------------------------------------------------

The inescapable logic of basic.life (3.8) is that within the
constructor, the result of accessing any non-static member data or
function is undefined (no doubt since they are accessed via the 'this'
pointer). This seems to be directly contradicted by class.cdtor
(12/7)...

Presumably most implementations will continue to allow valid access to
member data and non-virtual functions from constructors, but this does
seem to leave a large hole in the list of operations in constructors
that are guaranteed valid.

What is the position regarding access to member data after the
initialiser list has completed, but before returning from the
constructor? A literal reading of the standard suggests this is also
undefined.

Can anyone clarify the position?

Dave


--

Using Virtual Access
http://www.ashmount.com/va
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Martin D Kealey <martin@kcbbs.gen.nz>
Date: 1997/04/11
Raw View
In article <VA.00000009.2797b636@dlorde> dlorde@cix.compulink.co.uk wrote:
>> ----------------  3.8  Object Lifetime ---------
>> "1. The lifetime of an object of type T begins when:
>>   --if T is a class type with a non-trivial constructor, the
>>   constructor call has completed.
>>
>> "5. Before the lifetime of an object has started... any pointer that
>> refers to the storage location where the object will be... may be used
>> but only in limited  ways.
>>
>> "If the object will be or was of a non-POD class type, the program has
>> undefined behavior if:
>> --the pointer is used to access a non-static data  member or call a
>> non-static member function of the object"
>>
>> -------------------------------------------------------------------

> The inescapable logic of basic.life (3.8) is that within the
> constructor, the result of accessing any non-static member data or
> function is undefined (no doubt since they are accessed via the 'this'
> pointer). This seems to be directly contradicted by class.cdtor
> (12/7)...

[[WARNING: hand-waving that doesn't make reference to the actual standard]]

I think a reasonable inference can be drawn that even if the object as a
whole hasn't yet completed its constructor (or has already begun its
destructor), once the initialiser list has been completed (but before the
end of the destructor), the sub-objects from which it is composed *have*
finished their respective constructors (and have not yet started their
destructors).  So, access to those sub-objects is OK.

As for member functions, I guess an extra level of inference is required
(that the operations inside the function are OK because the sub-objects
have been constructed), which is admittedly rather more tenuous.

[I think my hands are beginning to blur with so much waving; I'd better
stop now before they become transparent.]

-Martin.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]