Date: Sat, 03 May 2014 23:11:52 +0800
Hi Hyman, this email is squarely on-topic for the UB study group mailing list, so I’ve taken the liberty of forwarding this onto it. You’ll need to subscribe at <http://www.open-std.org/pipermail/ub/> to reply. I’m not cross-posting to std-discussion because the lists are tied to different accounts of mine :P .
On 2014–05–02, at 12:14 AM, Hyman Rosen <hyman.rosen_at_[hidden]> wrote:
> 3.8/4 says:
>
> A program may end the lifetime of any object by reusing the storage which the object occupies
> ...
> For an object of a class type with a non-trivial destructor, the program is not required to call the
> destructor explicitly before the storage which the object occupies is reused or released; however
> ...
> any program that depends on the side effects produced by the destructor has undefined behavior.
>
> Suppose I have the following program:
>
> #include <stdio.h>
> #include <memory>
> int x;
> struct y { ~y() { ++x; } };
> void f() { y z; new(&z) y; }
> int main() { f(); printf("%d\n", x); }
>
> Questions:
> 1) What does the Standard mean when it says "depends on the side effects"? 1.9/12 says that
> side effects are changes in the state of the execution environment; what is a side effect that a
> program does not depend on? How can we examine a program to determine whether it depends
> on side effects of uncalled destructors?
>
> 2) It looks like the sample program has undefined behavior. Is that so, and should it be?
>
> 3) Would it still have undefined behavior if main() is changed to int main() { f(); }?
>
> 4) If not, what if x is declared volatile?
I’ll reply out of line for the benefit of participants who want to reply to the original post.
Your analysis seems to be along the lines that observable behavior (1.9/8) is not allowed to depend on whether an uncalled destructor ran. This is a reasonable angle in my opinion, but it runs into trouble.
My sense of the intent is that the mention of undefined behavior is not supposed to have normative force. It should be demoted to an informative note to avoid confusion. Since that paragraph already dictates that the destructor shall not be implicitly called, the behavior of the program is completely determined and there’s no reason that the fact of not being called shouldn’t be observable. What it’s trying to say is that the end-of-life semantics for that object are broken, and violated invariants are merely likely to result in UB during further execution.
In general, it’s bizarre to specify something and then forbid observation of it.
On 2014–05–02, at 12:14 AM, Hyman Rosen <hyman.rosen_at_[hidden]> wrote:
> 3.8/4 says:
>
> A program may end the lifetime of any object by reusing the storage which the object occupies
> ...
> For an object of a class type with a non-trivial destructor, the program is not required to call the
> destructor explicitly before the storage which the object occupies is reused or released; however
> ...
> any program that depends on the side effects produced by the destructor has undefined behavior.
>
> Suppose I have the following program:
>
> #include <stdio.h>
> #include <memory>
> int x;
> struct y { ~y() { ++x; } };
> void f() { y z; new(&z) y; }
> int main() { f(); printf("%d\n", x); }
>
> Questions:
> 1) What does the Standard mean when it says "depends on the side effects"? 1.9/12 says that
> side effects are changes in the state of the execution environment; what is a side effect that a
> program does not depend on? How can we examine a program to determine whether it depends
> on side effects of uncalled destructors?
>
> 2) It looks like the sample program has undefined behavior. Is that so, and should it be?
>
> 3) Would it still have undefined behavior if main() is changed to int main() { f(); }?
>
> 4) If not, what if x is declared volatile?
I’ll reply out of line for the benefit of participants who want to reply to the original post.
Your analysis seems to be along the lines that observable behavior (1.9/8) is not allowed to depend on whether an uncalled destructor ran. This is a reasonable angle in my opinion, but it runs into trouble.
My sense of the intent is that the mention of undefined behavior is not supposed to have normative force. It should be demoted to an informative note to avoid confusion. Since that paragraph already dictates that the destructor shall not be implicitly called, the behavior of the program is completely determined and there’s no reason that the fact of not being called shouldn’t be observable. What it’s trying to say is that the end-of-life semantics for that object are broken, and violated invariants are merely likely to result in UB during further execution.
In general, it’s bizarre to specify something and then forbid observation of it.
Received on 2014-05-03 18:12:23