<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">Note that this post from Herb arrived after <a href="http://www.open-std.org/pipermail/ub/2014-January/000418.html">http://www.open-std.org/pipermail/ub/2014-January/000418.html</a> but was sent before, so the thread got a little mixed up.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">On Thu, Jan 16, 2014 at 11:38 AM, Herb Sutter <span dir="ltr"><<a href="mailto:hsutter@microsoft.com" target="_blank" class="cremed">hsutter@microsoft.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Richard, it cannot mean that (or if it does, IMO we have an obvious bug) for at least two specific reasons I can think of (below), besides the general reasons
that it would not be sensical and would violate type safety.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u></span></p></div></div></blockquote><div><br></div><div>We do have an obvious bug in [basic.life]p1, "The lifetime of an object of type T begins when storage with the proper alignment and size for type T is obtained", if we interpret "obtained" as "obtained from the memory allocator". Even with strict uses of placement-new to change the type of memory, placement-new doesn't "obtain" any memory. If we interpret "obtained" as just "the programmer intends a region of storage to be available for a T", as I think Richard is suggesting, the bug is only that we need the wording to be clearer.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple">
<div><p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">First, objects must have unique addresses. Consider, still assuming B is trivially constructible:<u></u><u></u></span></p>
<p class="MsoNormal"> void *p = malloc(sizeof(B));</p></div></div></blockquote><div><br></div><div>The lifetime of a B starts some time after-or-including the malloc() call in the above line and the access of 'pb->i' two lines down. [basic.life]p5 ("Before the lifetime of an object has started ... The program has undefined behavior if ... the pointer is used to access a non-static data member")</div>
<div><br></div><div>The assignment to 'i' might start the lifetime of an 'int' subobject, but that's not enough to make the use of 'pb->i' defined if no 'B's lifetime has started.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><u></u><u></u></p>
<p class="MsoNormal"> B* pb = (B*)p;<br>
pb->i = 0;</p></div></div></blockquote><div><br></div><div>The lifetime of the B *ends* when its storage is re-used for the 'short' ([basic.life]p1 "The lifetime of an object of type T ends when ... the storage which the object occupies is reused"), as Daveed said. This happens some time after the access in the previous line, and the assignment two lines down.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple">
<p class="MsoNormal">
<u></u><u></u></p>
<p class="MsoNormal"> short* ps = (short*)p;<br>
*ps = 0;<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">This cannot possibly be construed as starting the lifetime of a B object and a short object, else they would have the same address, which is illegal. Am I missing
something?</span></p></div></blockquote><div><br></div><div>Both a B object and a short object have their lifetimes started in your code snippet, but the lifetimes don't overlap. </div><div><br></div><div>Confusingly, the start of these lifetimes is *not* called out in any particular line of code; it's implied by them. In particular, the casts don't have any lifetime effects (contra the straw man at <a href="http://www.open-std.org/pipermail/ub/2014-January/000406.html">http://www.open-std.org/pipermail/ub/2014-January/000406.html</a>). The code would be just as defined (or undefined) written as:</div>
<div><br></div><div><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px"> void *p = malloc(sizeof(B));<u></u><u></u></p><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px"> B* pb = (B*)p;<br>
short* ps = (short*)p;<br> pb->i = 0;<u></u><u></u></p><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px"> *ps = 0;</p><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px">
<br></p><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px">As Matt alluded to in <a href="http://www.open-std.org/pipermail/ub/2014-January/000456.html">http://www.open-std.org/pipermail/ub/2014-January/000456.html</a>, it might be possible to say that all lifetime effects are called out in explicit expressions without breaking C compatibility, *if* we instead say that accessing the members of objects with trivial constructors can be done outside of the lifetime of such objects. I have no idea whether that would be better or worse than saying that lifetime effects can be implied.</p>
<p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px"><br></p><p class="MsoNormal" style="font-family:arial,sans-serif;font-size:13px">Jeffrey</p></div></div></div></div>