Bug 15542 – pure function with no argument returning different values (with void-initialized static array)

Status
REOPENED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Mac OS X
Creation time
2016-01-10T08:39:13Z
Last change time
2024-12-13T18:46:27Z
Assigned to
No Owner
Creator
Timothee Cour
Moved to GitHub: dmd#19086 →

Comments

Comment #0 by timothee.cour2 — 2016-01-10T08:39:13Z
void main(){ auto a1=test4; int[6]temp; auto a2=test4; assert(a1==a2);// passes but... writeln(test4); writeln(test4); } pure int test4(){ int[4]a=void; return a[0]+a[1]+a[2]+a[3]; } // prints different valuse: -1907472476 -1907439709 DMD64 D Compiler v2.069-devel-6b2b521 which brings the question: should "pure" disallow void-initialized stack allocated data?
Comment #1 by schuetzm — 2016-01-19T18:45:15Z
Quoting https://dlang.org/spec/declaration.html#VoidInitializer : "If the Initializer is void, however, the variable is not initialized. If its value is used before it is set, undefined program behavior will result." Note how it says "undefined program behavior", not even "undefined value". So technically, the current behaviour is within the spec.
Comment #2 by razvan.nitu1305 — 2017-11-23T08:06:46Z
Maybe void initialization should be disallowed in pure functions.
Comment #3 by issues.dlang — 2017-11-23T16:23:56Z
I would argue that this simply isn't a bug. void initializers are an @system way to allow you to delay initialization so that you don't default-initialize a variable and then assign to it again shortly thereafter. You're never supposed to actually use the value of a void initialized variable any more than it's advised to use a variable in C/C++ that you didn't initialize and thus is filled with garbage. The fact that the pure function returns different values for different calls is simply a result of failing to do your due diligence with an @system function and make sure that it's actually @safe in spite of the @system operations that it's doing. You'd have the same problem if you made it do pointer arithmetic that made it point past the end of a buffer. There are plenty of other ways to end up pointing to varying things whenever you violate @safe. There's nothing particularly special about the void initializer in that regard. You'd basically have to force all pure functions to be @safe if you wanted to avoid this problem.
Comment #4 by ag0aep6g — 2017-11-23T16:43:15Z
(In reply to Marc Schütz from comment #1) > Note how it says "undefined program behavior", not even "undefined value". > So technically, the current behaviour is within the spec. (In reply to Jonathan M Davis from comment #3) > You'd basically have to force all pure functions to be @safe if you wanted > to avoid this problem. Note that the test code still compiles even when you add `@safe`. Void initialization of value types is considered `@safe`.
Comment #5 by issues.dlang — 2017-11-23T21:41:57Z
(In reply to ag0aep6g from comment #4) > Note that the test code still compiles even when you add `@safe`. Void > initialization of value types is considered `@safe`. Hmmm. I'm inclined to think that that's a bug, but I suppose that it depends on what types it lets you void initialize. I guess that if it's just ints and floats and whatnot in the struct, then that doesn't actually pose a memory safety problem and wouldn't need to be marked @system, but it still seems wrong. Either way, I think that it's pretty clear that you're dealing with undefined behavior if you use a void-initialized object before giving it a proper value, and I don't see any reason to treat pure as special in that regard. As long as the variable is given a proper value, then there is no purity issue, and regardless of whether @safety concerns really apply in all cases with void-inialization, the concept is basically the same. When the programmer void-initializes something, they're essentially promising that they'll do the right thing and give the variablie a value before using it so that the normal guarantees are in place.
Comment #6 by schveiguy — 2017-11-24T16:03:18Z
(In reply to Jonathan M Davis from comment #5) > (In reply to ag0aep6g from comment #4) > > Note that the test code still compiles even when you add `@safe`. Void > > initialization of value types is considered `@safe`. > > Hmmm. I'm inclined to think that that's a bug, but I suppose that it depends > on what types it lets you void initialize. I guess that if it's just ints > and floats and whatnot in the struct, then that doesn't actually pose a > memory safety problem and wouldn't need to be marked @system, but it still > seems wrong. That particular case is not a bug. It's perfectly memory safe to look at/use your own stack frame without initialization, as long as data doesn't contain a reference. > Either way, I think that it's pretty clear that you're dealing with > undefined behavior if you use a void-initialized object before giving it a > proper value, and I don't see any reason to treat pure as special in that > regard. Agree. This is not a bug, just bad code.
Comment #7 by ag0aep6g — 2017-11-27T12:18:43Z
(In reply to Steven Schveighoffer from comment #6) > It's perfectly memory safe to look at/use > your own stack frame without initialization, as long as data doesn't contain > a reference. It still has undefined behavior, and `@safe` is supposed to rule out undefined behavior. So, according to the spec, `@safe` should prevent the code from compiling. This is all about `@safe` and has nothing to do with `pure`, though. I've filed a new issue: issue 18016.
Comment #8 by ag0aep6g — 2023-01-05T18:53:19Z
This issue was closed because the presented program was invalid at the time. It was invalid because using the value of an uninitialized variable used to trigger undefined behavior. Walter has since changed the spec, allowing such use of uninitialized variables [1]. The presented program does not trigger undefined behavior anymore, at least not in the way it did when the issue was closed. So the reason for closing is no longer true. Reopening. [1] https://github.com/dlang/dlang.org/pull/2260
Comment #9 by razvan.nitu1305 — 2023-06-28T14:34:27Z
*** Issue 14823 has been marked as a duplicate of this issue. ***
Comment #10 by robert.schadek — 2024-12-13T18:46:27Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19086 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB