Difference in the end of lifetime rules?












33














https://en.cppreference.com/w/cpp/language/lifetime in Notes section has this code, reproduced here:



struct A {
int* p;
~A() { std::cout << *p; } // if n outlives a, prints 123
};
void f() {
A a;
int n = 123; // if n does not outlive a, this is optimized out (dead store)
a.p = &n;
}


What is it trying to say in this Notes section?



From what I understand, the code is UB (or is it) as it's clear that n does not outlive a.



What does it mean by:




difference in the end of lifetime rules between non-class objects (end
of storage duration) and class objects (reverse order of construction)
matters




But it does not say matter how.



I am very confused by this entire section.










share|improve this question


















  • 2




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    Dec 14 '18 at 19:34












  • @NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
    – Brian
    Dec 14 '18 at 19:37










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    Dec 14 '18 at 19:54






  • 2




    This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
    – T.C.
    Dec 14 '18 at 20:49
















33














https://en.cppreference.com/w/cpp/language/lifetime in Notes section has this code, reproduced here:



struct A {
int* p;
~A() { std::cout << *p; } // if n outlives a, prints 123
};
void f() {
A a;
int n = 123; // if n does not outlive a, this is optimized out (dead store)
a.p = &n;
}


What is it trying to say in this Notes section?



From what I understand, the code is UB (or is it) as it's clear that n does not outlive a.



What does it mean by:




difference in the end of lifetime rules between non-class objects (end
of storage duration) and class objects (reverse order of construction)
matters




But it does not say matter how.



I am very confused by this entire section.










share|improve this question


















  • 2




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    Dec 14 '18 at 19:34












  • @NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
    – Brian
    Dec 14 '18 at 19:37










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    Dec 14 '18 at 19:54






  • 2




    This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
    – T.C.
    Dec 14 '18 at 20:49














33












33








33


6





https://en.cppreference.com/w/cpp/language/lifetime in Notes section has this code, reproduced here:



struct A {
int* p;
~A() { std::cout << *p; } // if n outlives a, prints 123
};
void f() {
A a;
int n = 123; // if n does not outlive a, this is optimized out (dead store)
a.p = &n;
}


What is it trying to say in this Notes section?



From what I understand, the code is UB (or is it) as it's clear that n does not outlive a.



What does it mean by:




difference in the end of lifetime rules between non-class objects (end
of storage duration) and class objects (reverse order of construction)
matters




But it does not say matter how.



I am very confused by this entire section.










share|improve this question













https://en.cppreference.com/w/cpp/language/lifetime in Notes section has this code, reproduced here:



struct A {
int* p;
~A() { std::cout << *p; } // if n outlives a, prints 123
};
void f() {
A a;
int n = 123; // if n does not outlive a, this is optimized out (dead store)
a.p = &n;
}


What is it trying to say in this Notes section?



From what I understand, the code is UB (or is it) as it's clear that n does not outlive a.



What does it mean by:




difference in the end of lifetime rules between non-class objects (end
of storage duration) and class objects (reverse order of construction)
matters




But it does not say matter how.



I am very confused by this entire section.







c++ language-lawyer undefined-behavior






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 14 '18 at 19:26









PoweredByRicePoweredByRice

1,2251321




1,2251321








  • 2




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    Dec 14 '18 at 19:34












  • @NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
    – Brian
    Dec 14 '18 at 19:37










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    Dec 14 '18 at 19:54






  • 2




    This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
    – T.C.
    Dec 14 '18 at 20:49














  • 2




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    Dec 14 '18 at 19:34












  • @NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
    – Brian
    Dec 14 '18 at 19:37










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    Dec 14 '18 at 19:54






  • 2




    This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
    – T.C.
    Dec 14 '18 at 20:49








2




2




I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
– NathanOliver
Dec 14 '18 at 19:34






I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
– NathanOliver
Dec 14 '18 at 19:34














@NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
– Brian
Dec 14 '18 at 19:37




@NathanOliver I think it might be insinuating that n does outlive a because a is destroyed just before the closing brace and n is destroyed at the closing brace. I'm not convinced that this is true, though.
– Brian
Dec 14 '18 at 19:37












I thought reverse order destruction would mean that n is destroyed before a leading to UB.
– Galik
Dec 14 '18 at 19:54




I thought reverse order destruction would mean that n is destroyed before a leading to UB.
– Galik
Dec 14 '18 at 19:54




2




2




This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
– T.C.
Dec 14 '18 at 20:49




This is core issue 2256. We took this example (which Clang "miscompiles" according to the current rules) from one of the core reflector posts on this subject.
– T.C.
Dec 14 '18 at 20:49












2 Answers
2






active

oldest

votes


















27














This is an odd aspect of C++'s lifetime rules. [basic.life]/1 tells us that an object's lifetime ends:





  • if T is a class type with a non-trivial destructor ([class.dtor]), the destructor call starts, or

  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).




Emphasis added. int is not a "class type with a non-trivial destructor", so its lifetime only ends when the storage it occupies is released. By contrast, A is a class type with a non-trivial destructor", so its lifetime ends when the destructor gets called.



The storage for a scope is released when the scope exits, pursuant to [basic.stc.auto]/1:




The storage for [variables with automatic storage duration] lasts until the block in which they are created exits.




But automatic variables are destroyed in accord with [stmt.jump]/2:




On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction.




Notice that the order of destruction is specified, but the order of automatic storage release is not specified. This means that the implementation could release the storage right after each variable is destroyed, or release it all at once later, or in some arbitrary other order.



Now, the fact that it uses the singular for storage ("the storage for ... lasts") rather than talking about each variable individually may suggest that the intent is for the storage as a whole to be released at once for that scope. But there is no explicit statement of this in the standard. So as long as a variable is destroyed before its storage is released, any ordering of destruction vs. release appears to be legal.



This means it is entirely possible for the code to work, for n to outlive a. But it is unspecified whether it does work.






share|improve this answer



















  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    Dec 14 '18 at 20:07






  • 2




    @Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
    – Nicol Bolas
    Dec 14 '18 at 20:13






  • 3




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    Dec 14 '18 at 20:23






  • 3




    By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
    – Brian
    Dec 14 '18 at 20:24






  • 3




    @SoronelHaetir That's covered by as-if.
    – T.C.
    Dec 14 '18 at 21:21



















10














This example is borrowed from Core Language Issue 2256:




Section: 6.8 [basic.life] Status: drafting Submitter: Richard Smith Date: 2016-03-30



According to 6.4 [basic.lookup] bullet 1.4, the following example has defined behavior because the lifetime of n extends until its storage is released, which is after a's destructor runs:



  void f() { 
struct A { int *p; ~A() { *p = 0; } } a;
int n;
a.p = &n;
}


It would be more consistent if the end of the lifetime of all objects, regardless of whether they have a non-trivial destructor, were treated the same.



Notes from the March, 2018 meeting:



CWG agreed with the suggested direction.




The key idea is, whether the lifetime of an object ends at its destruction or at the time its memory is released may affect the semantic of a program. In the example,




  1. if the lifetime of n ends at the destruction of n, the program is undefined;


  2. if the lifetime of n ends until the memory is released, the program has defined behavior1.



Hence it requires further discussion to determine when the lifetime of an object ends.





1 This is because Core Language Issue 2115:




Section: 9.6 [stmt.jump] Status: drafting Submitter: Richard Smith Date: 2015-04-16



The relative ordering between destruction of automatic variables on exit from a block and the release of the variables' storage is not specified by the Standard: are all the destructors executed first and then the storage released, or are they interleaved?



Notes from the February, 2016 meeting:



CWG agreed that the storage should persist until all destructions are complete, although the “as-if” rule would allow for unobservable optimizations of this ordering.




The intent is that the memory release of automatic variables happens after all destructions are complete.






share|improve this answer























  • Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
    – supercat
    Dec 14 '18 at 22:19










  • @supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
    – Nicol Bolas
    Dec 14 '18 at 22:22










  • Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
    – Brian
    Dec 14 '18 at 22:35










  • @NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
    – supercat
    Dec 14 '18 at 22:37










  • @supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
    – Nicol Bolas
    Dec 15 '18 at 0:24













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53785791%2fdifference-in-the-end-of-lifetime-rules%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









27














This is an odd aspect of C++'s lifetime rules. [basic.life]/1 tells us that an object's lifetime ends:





  • if T is a class type with a non-trivial destructor ([class.dtor]), the destructor call starts, or

  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).




Emphasis added. int is not a "class type with a non-trivial destructor", so its lifetime only ends when the storage it occupies is released. By contrast, A is a class type with a non-trivial destructor", so its lifetime ends when the destructor gets called.



The storage for a scope is released when the scope exits, pursuant to [basic.stc.auto]/1:




The storage for [variables with automatic storage duration] lasts until the block in which they are created exits.




But automatic variables are destroyed in accord with [stmt.jump]/2:




On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction.




Notice that the order of destruction is specified, but the order of automatic storage release is not specified. This means that the implementation could release the storage right after each variable is destroyed, or release it all at once later, or in some arbitrary other order.



Now, the fact that it uses the singular for storage ("the storage for ... lasts") rather than talking about each variable individually may suggest that the intent is for the storage as a whole to be released at once for that scope. But there is no explicit statement of this in the standard. So as long as a variable is destroyed before its storage is released, any ordering of destruction vs. release appears to be legal.



This means it is entirely possible for the code to work, for n to outlive a. But it is unspecified whether it does work.






share|improve this answer



















  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    Dec 14 '18 at 20:07






  • 2




    @Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
    – Nicol Bolas
    Dec 14 '18 at 20:13






  • 3




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    Dec 14 '18 at 20:23






  • 3




    By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
    – Brian
    Dec 14 '18 at 20:24






  • 3




    @SoronelHaetir That's covered by as-if.
    – T.C.
    Dec 14 '18 at 21:21
















27














This is an odd aspect of C++'s lifetime rules. [basic.life]/1 tells us that an object's lifetime ends:





  • if T is a class type with a non-trivial destructor ([class.dtor]), the destructor call starts, or

  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).




Emphasis added. int is not a "class type with a non-trivial destructor", so its lifetime only ends when the storage it occupies is released. By contrast, A is a class type with a non-trivial destructor", so its lifetime ends when the destructor gets called.



The storage for a scope is released when the scope exits, pursuant to [basic.stc.auto]/1:




The storage for [variables with automatic storage duration] lasts until the block in which they are created exits.




But automatic variables are destroyed in accord with [stmt.jump]/2:




On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction.




Notice that the order of destruction is specified, but the order of automatic storage release is not specified. This means that the implementation could release the storage right after each variable is destroyed, or release it all at once later, or in some arbitrary other order.



Now, the fact that it uses the singular for storage ("the storage for ... lasts") rather than talking about each variable individually may suggest that the intent is for the storage as a whole to be released at once for that scope. But there is no explicit statement of this in the standard. So as long as a variable is destroyed before its storage is released, any ordering of destruction vs. release appears to be legal.



This means it is entirely possible for the code to work, for n to outlive a. But it is unspecified whether it does work.






share|improve this answer



















  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    Dec 14 '18 at 20:07






  • 2




    @Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
    – Nicol Bolas
    Dec 14 '18 at 20:13






  • 3




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    Dec 14 '18 at 20:23






  • 3




    By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
    – Brian
    Dec 14 '18 at 20:24






  • 3




    @SoronelHaetir That's covered by as-if.
    – T.C.
    Dec 14 '18 at 21:21














27












27








27






This is an odd aspect of C++'s lifetime rules. [basic.life]/1 tells us that an object's lifetime ends:





  • if T is a class type with a non-trivial destructor ([class.dtor]), the destructor call starts, or

  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).




Emphasis added. int is not a "class type with a non-trivial destructor", so its lifetime only ends when the storage it occupies is released. By contrast, A is a class type with a non-trivial destructor", so its lifetime ends when the destructor gets called.



The storage for a scope is released when the scope exits, pursuant to [basic.stc.auto]/1:




The storage for [variables with automatic storage duration] lasts until the block in which they are created exits.




But automatic variables are destroyed in accord with [stmt.jump]/2:




On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction.




Notice that the order of destruction is specified, but the order of automatic storage release is not specified. This means that the implementation could release the storage right after each variable is destroyed, or release it all at once later, or in some arbitrary other order.



Now, the fact that it uses the singular for storage ("the storage for ... lasts") rather than talking about each variable individually may suggest that the intent is for the storage as a whole to be released at once for that scope. But there is no explicit statement of this in the standard. So as long as a variable is destroyed before its storage is released, any ordering of destruction vs. release appears to be legal.



This means it is entirely possible for the code to work, for n to outlive a. But it is unspecified whether it does work.






share|improve this answer














This is an odd aspect of C++'s lifetime rules. [basic.life]/1 tells us that an object's lifetime ends:





  • if T is a class type with a non-trivial destructor ([class.dtor]), the destructor call starts, or

  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).




Emphasis added. int is not a "class type with a non-trivial destructor", so its lifetime only ends when the storage it occupies is released. By contrast, A is a class type with a non-trivial destructor", so its lifetime ends when the destructor gets called.



The storage for a scope is released when the scope exits, pursuant to [basic.stc.auto]/1:




The storage for [variables with automatic storage duration] lasts until the block in which they are created exits.




But automatic variables are destroyed in accord with [stmt.jump]/2:




On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction.




Notice that the order of destruction is specified, but the order of automatic storage release is not specified. This means that the implementation could release the storage right after each variable is destroyed, or release it all at once later, or in some arbitrary other order.



Now, the fact that it uses the singular for storage ("the storage for ... lasts") rather than talking about each variable individually may suggest that the intent is for the storage as a whole to be released at once for that scope. But there is no explicit statement of this in the standard. So as long as a variable is destroyed before its storage is released, any ordering of destruction vs. release appears to be legal.



This means it is entirely possible for the code to work, for n to outlive a. But it is unspecified whether it does work.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 14 '18 at 20:14

























answered Dec 14 '18 at 19:43









Nicol BolasNicol Bolas

283k33467642




283k33467642








  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    Dec 14 '18 at 20:07






  • 2




    @Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
    – Nicol Bolas
    Dec 14 '18 at 20:13






  • 3




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    Dec 14 '18 at 20:23






  • 3




    By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
    – Brian
    Dec 14 '18 at 20:24






  • 3




    @SoronelHaetir That's covered by as-if.
    – T.C.
    Dec 14 '18 at 21:21














  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    Dec 14 '18 at 20:07






  • 2




    @Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
    – Nicol Bolas
    Dec 14 '18 at 20:13






  • 3




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    Dec 14 '18 at 20:23






  • 3




    By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
    – Brian
    Dec 14 '18 at 20:24






  • 3




    @SoronelHaetir That's covered by as-if.
    – T.C.
    Dec 14 '18 at 21:21








1




1




@SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
– Nicol Bolas
Dec 14 '18 at 20:07




@SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
– Nicol Bolas
Dec 14 '18 at 20:07




2




2




@Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
– Nicol Bolas
Dec 14 '18 at 20:13




@Galik: "I still (from that wording) don't see why each object won't be destructed then deallocated in turn." I'm not saying that it couldn't; I'm saying that it is not required. Which is why the cppreference page speaks in hypothetical terms about whether it works or not. Because it is unspecified.
– Nicol Bolas
Dec 14 '18 at 20:13




3




3




@Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
– Nicol Bolas
Dec 14 '18 at 20:23




@Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
– Nicol Bolas
Dec 14 '18 at 20:23




3




3




By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
– Brian
Dec 14 '18 at 20:24




By "we" I meant the C++ community, by proposing to the committee that such a change be made. By "can", I meant whether or not this would have a decent chance at getting accepted.
– Brian
Dec 14 '18 at 20:24




3




3




@SoronelHaetir That's covered by as-if.
– T.C.
Dec 14 '18 at 21:21




@SoronelHaetir That's covered by as-if.
– T.C.
Dec 14 '18 at 21:21













10














This example is borrowed from Core Language Issue 2256:




Section: 6.8 [basic.life] Status: drafting Submitter: Richard Smith Date: 2016-03-30



According to 6.4 [basic.lookup] bullet 1.4, the following example has defined behavior because the lifetime of n extends until its storage is released, which is after a's destructor runs:



  void f() { 
struct A { int *p; ~A() { *p = 0; } } a;
int n;
a.p = &n;
}


It would be more consistent if the end of the lifetime of all objects, regardless of whether they have a non-trivial destructor, were treated the same.



Notes from the March, 2018 meeting:



CWG agreed with the suggested direction.




The key idea is, whether the lifetime of an object ends at its destruction or at the time its memory is released may affect the semantic of a program. In the example,




  1. if the lifetime of n ends at the destruction of n, the program is undefined;


  2. if the lifetime of n ends until the memory is released, the program has defined behavior1.



Hence it requires further discussion to determine when the lifetime of an object ends.





1 This is because Core Language Issue 2115:




Section: 9.6 [stmt.jump] Status: drafting Submitter: Richard Smith Date: 2015-04-16



The relative ordering between destruction of automatic variables on exit from a block and the release of the variables' storage is not specified by the Standard: are all the destructors executed first and then the storage released, or are they interleaved?



Notes from the February, 2016 meeting:



CWG agreed that the storage should persist until all destructions are complete, although the “as-if” rule would allow for unobservable optimizations of this ordering.




The intent is that the memory release of automatic variables happens after all destructions are complete.






share|improve this answer























  • Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
    – supercat
    Dec 14 '18 at 22:19










  • @supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
    – Nicol Bolas
    Dec 14 '18 at 22:22










  • Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
    – Brian
    Dec 14 '18 at 22:35










  • @NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
    – supercat
    Dec 14 '18 at 22:37










  • @supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
    – Nicol Bolas
    Dec 15 '18 at 0:24


















10














This example is borrowed from Core Language Issue 2256:




Section: 6.8 [basic.life] Status: drafting Submitter: Richard Smith Date: 2016-03-30



According to 6.4 [basic.lookup] bullet 1.4, the following example has defined behavior because the lifetime of n extends until its storage is released, which is after a's destructor runs:



  void f() { 
struct A { int *p; ~A() { *p = 0; } } a;
int n;
a.p = &n;
}


It would be more consistent if the end of the lifetime of all objects, regardless of whether they have a non-trivial destructor, were treated the same.



Notes from the March, 2018 meeting:



CWG agreed with the suggested direction.




The key idea is, whether the lifetime of an object ends at its destruction or at the time its memory is released may affect the semantic of a program. In the example,




  1. if the lifetime of n ends at the destruction of n, the program is undefined;


  2. if the lifetime of n ends until the memory is released, the program has defined behavior1.



Hence it requires further discussion to determine when the lifetime of an object ends.





1 This is because Core Language Issue 2115:




Section: 9.6 [stmt.jump] Status: drafting Submitter: Richard Smith Date: 2015-04-16



The relative ordering between destruction of automatic variables on exit from a block and the release of the variables' storage is not specified by the Standard: are all the destructors executed first and then the storage released, or are they interleaved?



Notes from the February, 2016 meeting:



CWG agreed that the storage should persist until all destructions are complete, although the “as-if” rule would allow for unobservable optimizations of this ordering.




The intent is that the memory release of automatic variables happens after all destructions are complete.






share|improve this answer























  • Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
    – supercat
    Dec 14 '18 at 22:19










  • @supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
    – Nicol Bolas
    Dec 14 '18 at 22:22










  • Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
    – Brian
    Dec 14 '18 at 22:35










  • @NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
    – supercat
    Dec 14 '18 at 22:37










  • @supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
    – Nicol Bolas
    Dec 15 '18 at 0:24
















10












10








10






This example is borrowed from Core Language Issue 2256:




Section: 6.8 [basic.life] Status: drafting Submitter: Richard Smith Date: 2016-03-30



According to 6.4 [basic.lookup] bullet 1.4, the following example has defined behavior because the lifetime of n extends until its storage is released, which is after a's destructor runs:



  void f() { 
struct A { int *p; ~A() { *p = 0; } } a;
int n;
a.p = &n;
}


It would be more consistent if the end of the lifetime of all objects, regardless of whether they have a non-trivial destructor, were treated the same.



Notes from the March, 2018 meeting:



CWG agreed with the suggested direction.




The key idea is, whether the lifetime of an object ends at its destruction or at the time its memory is released may affect the semantic of a program. In the example,




  1. if the lifetime of n ends at the destruction of n, the program is undefined;


  2. if the lifetime of n ends until the memory is released, the program has defined behavior1.



Hence it requires further discussion to determine when the lifetime of an object ends.





1 This is because Core Language Issue 2115:




Section: 9.6 [stmt.jump] Status: drafting Submitter: Richard Smith Date: 2015-04-16



The relative ordering between destruction of automatic variables on exit from a block and the release of the variables' storage is not specified by the Standard: are all the destructors executed first and then the storage released, or are they interleaved?



Notes from the February, 2016 meeting:



CWG agreed that the storage should persist until all destructions are complete, although the “as-if” rule would allow for unobservable optimizations of this ordering.




The intent is that the memory release of automatic variables happens after all destructions are complete.






share|improve this answer














This example is borrowed from Core Language Issue 2256:




Section: 6.8 [basic.life] Status: drafting Submitter: Richard Smith Date: 2016-03-30



According to 6.4 [basic.lookup] bullet 1.4, the following example has defined behavior because the lifetime of n extends until its storage is released, which is after a's destructor runs:



  void f() { 
struct A { int *p; ~A() { *p = 0; } } a;
int n;
a.p = &n;
}


It would be more consistent if the end of the lifetime of all objects, regardless of whether they have a non-trivial destructor, were treated the same.



Notes from the March, 2018 meeting:



CWG agreed with the suggested direction.




The key idea is, whether the lifetime of an object ends at its destruction or at the time its memory is released may affect the semantic of a program. In the example,




  1. if the lifetime of n ends at the destruction of n, the program is undefined;


  2. if the lifetime of n ends until the memory is released, the program has defined behavior1.



Hence it requires further discussion to determine when the lifetime of an object ends.





1 This is because Core Language Issue 2115:




Section: 9.6 [stmt.jump] Status: drafting Submitter: Richard Smith Date: 2015-04-16



The relative ordering between destruction of automatic variables on exit from a block and the release of the variables' storage is not specified by the Standard: are all the destructors executed first and then the storage released, or are they interleaved?



Notes from the February, 2016 meeting:



CWG agreed that the storage should persist until all destructions are complete, although the “as-if” rule would allow for unobservable optimizations of this ordering.




The intent is that the memory release of automatic variables happens after all destructions are complete.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 15 '18 at 3:28

























answered Dec 14 '18 at 21:04









xskxzrxskxzr

6,10582052




6,10582052












  • Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
    – supercat
    Dec 14 '18 at 22:19










  • @supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
    – Nicol Bolas
    Dec 14 '18 at 22:22










  • Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
    – Brian
    Dec 14 '18 at 22:35










  • @NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
    – supercat
    Dec 14 '18 at 22:37










  • @supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
    – Nicol Bolas
    Dec 15 '18 at 0:24




















  • Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
    – supercat
    Dec 14 '18 at 22:19










  • @supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
    – Nicol Bolas
    Dec 14 '18 at 22:22










  • Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
    – Brian
    Dec 14 '18 at 22:35










  • @NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
    – supercat
    Dec 14 '18 at 22:37










  • @supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
    – Nicol Bolas
    Dec 15 '18 at 0:24


















Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
– supercat
Dec 14 '18 at 22:19




Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy? If the goal is to allow aliasing-related optimization, it would seem both simpler and more effective to simply say that loads and stores of seemingly-unrelated lvalues are generally unsequenced, and specify situations where lvaues must be recognized as related, or operations upon them recognized as sequenced.
– supercat
Dec 14 '18 at 22:19












@supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
– Nicol Bolas
Dec 14 '18 at 22:22




@supercat: "Is there any real need for plain-old-data objects have a lifetime separate from that of the storage they occupy?" Yes. Scalar lifetime analysis can catch people using uninitialized memory and other similar errors. But that requires that scalars have lifetimes, that you can point to a piece of memory and know exactly the (nested set of) objects that live there.
– Nicol Bolas
Dec 14 '18 at 22:22












Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
– Brian
Dec 14 '18 at 22:35




Just to be clear: this means that CWG has agreed that this code snippet should have undefined behaviour, and the standard should be updated to make it so?
– Brian
Dec 14 '18 at 22:35












@NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
– supercat
Dec 14 '18 at 22:37




@NicolBolas: Having explicit directives to either say that a certain region of storage should be treated as holding Indeterminate Value, or that any bytes within a region of storage that hold Indeterminate Value should be changed to hold Unspecified values, would seem more useful, for purposes of diagnostics and optimization, than trying to use lifetime rules for that purpose.
– supercat
Dec 14 '18 at 22:37












@supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
– Nicol Bolas
Dec 15 '18 at 0:24






@supercat: But there are "explicit directives" to do just that. They're called "destroying the object" and "creating an object without initializing it". They already exist and already have useful semantic meanings.
– Nicol Bolas
Dec 15 '18 at 0:24




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53785791%2fdifference-in-the-end-of-lifetime-rules%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Plaza Victoria

Puebla de Zaragoza

Musa