Bug 1084 – lazy variadic parameters break in strange way
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D1 (retired)
Platform
All
OS
All
Creation time
2007-03-28T13:13:00Z
Last change time
2019-03-29T13:58:16Z
Keywords
accepts-invalid
Assigned to
No Owner
Creator
FeepingCreature
Comments
Comment #0 by default_357-line — 2007-03-28T13:13:00Z
Consider the following code.
import std.stdio;
char[] test() { writefln("Eval test"); return "bla"; }
void test2(lazy char[][] bla ...) { foreach (elem; bla) writefln(elem);}
void main() { test2(test, test); }
It compiles (verified gdc .21/dmd .175 by h3 [I couldn't find anybody with 1.010; volunteers appreciated]), but when run, outputs
Eval test
Eval test
bla
<garbage>
Some observations:
- returning "bla".dup doesn't help.
- The garbage seems to be an array with the same length as whatever was returned from test. I did not check to see where the pointer goes. Maybe that might offer some clue.
If this has already been fixed in 1.010, sorry for wasting your time.
greetings&stuffies --downs
Comment #1 by fvbommel — 2007-03-28T14:57:06Z
What seems to be happening here:
The parameter list of test2 is "lazy char[][] bla ...".
The type of the parameter is an array of char[]s. Because of the "..." this array is implicitly constructed on the stack when the function is called. However, because of the "lazy" this implicitly construction is put into a delegate that is then pushed onto the stack as the actual parameter.
The problem with this is that the delegate constructs an array on the stack and then returns _that_ array.
So the "lazy" delegate is returning a reference to data on the stack (in it's own stack-frame). This is always a Bad Idea.
(I guess combining "lazy" and "..." is not a good idea)
What you may have meant was:
---
/// A call constructs an array on the stack and pass a reference.
/// Passed "parameters" are evaluated before calling.
void test2(char[][] bla ...) {
foreach (elem; bla) writefln(elem);
}
---
or:
---
/// A call constructs an array of delegates on the stack and pass a reference to that.
/// Passed "parameters" aren't evaluated until used.
void test2(char[] delegate()[] bla ...) {
foreach (elem; bla) writefln(elem());
}
---
This isn't wrong-code, the bug is in the user's code. Changing to accepts-invalid.
(Perhaps lazy []... should be illegal?)
On DMD2, it displays:
bug(12): Error: escaping reference to local __arrayArg502
So it's a D1-only issue.
Comment #4 by default_357-line — 2019-03-29T13:58:16Z
This code started working at 2.067.1. It seems to be creating the array lazily when the foreach references the parameter, which is a sane way to go. In any case, fixed.