Difference in the end of lifetime rules?











up vote
22
down vote

favorite
4












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


















  • 1




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    11 hours ago












  • @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
    11 hours ago










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    11 hours ago






  • 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.
    10 hours ago















up vote
22
down vote

favorite
4












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


















  • 1




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    11 hours ago












  • @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
    11 hours ago










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    11 hours ago






  • 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.
    10 hours ago













up vote
22
down vote

favorite
4









up vote
22
down vote

favorite
4






4





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 11 hours ago









PoweredByRice

1,1651220




1,1651220








  • 1




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    11 hours ago












  • @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
    11 hours ago










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    11 hours ago






  • 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.
    10 hours ago














  • 1




    I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
    – NathanOliver
    11 hours ago












  • @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
    11 hours ago










  • I thought reverse order destruction would mean that n is destroyed before a leading to UB.
    – Galik
    11 hours ago






  • 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.
    10 hours ago








1




1




I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
– NathanOliver
11 hours ago






I'm not sure what they are trying to say in the notes section. AFAIK this is UB per the standard.
– NathanOliver
11 hours ago














@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
11 hours ago




@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
11 hours ago












I thought reverse order destruction would mean that n is destroyed before a leading to UB.
– Galik
11 hours ago




I thought reverse order destruction would mean that n is destroyed before a leading to UB.
– Galik
11 hours ago




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.
10 hours ago




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.
10 hours ago












2 Answers
2






active

oldest

votes

















up vote
21
down vote













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
    10 hours ago






  • 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
    10 hours ago






  • 2




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @SoronelHaetir That's covered by as-if.
    – T.C.
    9 hours ago


















up vote
6
down vote













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
    8 hours ago










  • @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
    8 hours ago










  • 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
    8 hours ago










  • @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
    8 hours ago










  • @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
    6 hours ago













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',
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








up vote
21
down vote













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
    10 hours ago






  • 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
    10 hours ago






  • 2




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @SoronelHaetir That's covered by as-if.
    – T.C.
    9 hours ago















up vote
21
down vote













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
    10 hours ago






  • 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
    10 hours ago






  • 2




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @SoronelHaetir That's covered by as-if.
    – T.C.
    9 hours ago













up vote
21
down vote










up vote
21
down vote









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 10 hours ago

























answered 11 hours ago









Nicol Bolas

281k33461636




281k33461636








  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @SoronelHaetir That's covered by as-if.
    – T.C.
    9 hours ago














  • 1




    @SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
    – Nicol Bolas
    10 hours ago






  • 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
    10 hours ago






  • 2




    @SoronelHaetir That's covered by as-if.
    – T.C.
    9 hours ago








1




1




@SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
– Nicol Bolas
10 hours ago




@SergeyA: Upon further investigation, things aren't quite that simple. My answer has been revised accordingly.
– Nicol Bolas
10 hours ago




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
10 hours ago




@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
10 hours ago




2




2




@Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
– Nicol Bolas
10 hours ago




@Brian: Who is "we"? Can the committee? Sure; there have been some discussion on that. Can random users on SO? No.
– Nicol Bolas
10 hours ago




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
10 hours ago




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
10 hours ago




2




2




@SoronelHaetir That's covered by as-if.
– T.C.
9 hours ago




@SoronelHaetir That's covered by as-if.
– T.C.
9 hours ago












up vote
6
down vote













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
    8 hours ago










  • @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
    8 hours ago










  • 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
    8 hours ago










  • @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
    8 hours ago










  • @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
    6 hours ago

















up vote
6
down vote













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
    8 hours ago










  • @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
    8 hours ago










  • 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
    8 hours ago










  • @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
    8 hours ago










  • @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
    6 hours ago















up vote
6
down vote










up vote
6
down vote









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 3 hours ago

























answered 9 hours ago









xskxzr

5,85182051




5,85182051












  • 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
    8 hours ago










  • @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
    8 hours ago










  • 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
    8 hours ago










  • @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
    8 hours ago










  • @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
    6 hours ago




















  • 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
    8 hours ago










  • @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
    8 hours ago










  • 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
    8 hours ago










  • @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
    8 hours ago










  • @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
    6 hours ago


















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
8 hours ago




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
8 hours ago












@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
8 hours ago




@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
8 hours ago












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
8 hours ago




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
8 hours ago












@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
8 hours ago




@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
8 hours ago












@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
6 hours ago






@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
6 hours ago




















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

Quarter-circle Tiles

build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

Mont Emei