digitalmars.D - Question of delegate literals and return from function(GDC,DMD,LDC)
- amaury pouly (43/43) Jan 31 2009 Hello,
- Jarrett Billingsley (13/14) Jan 31 2009 ected behaviour ? The second solution must always work but I'm unsure ab...
- downs (14/33) Feb 01 2009 tools version:
- Daniel Keep (5/42) Feb 01 2009 I was tempted to post mine out of sheer bloody-mindedness, except that
- Steven Schveighoffer (9/59) Feb 02 2009 Expected behavior. Function arguments *are* stack parameters. Even tho...
Hello, I have a little question about D: I want to have a function returning a delegate and more precisely a delegate literal that uses one of the arguments of the function. Here is an example: int delegate(int) test(int[] tab) { return (int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; }; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; } Of course this example is stupid but the idea is here. The point is that if I compile and run this code with DMD it works fine whereas it segfaults with GDC and LDC(LLVM D). I also know a fix for the segfault with both GDC and LDC: int delegate(int) test(int[] tab) { struct Foo { int[] tab; int fn(int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; } } Foo *f=new Foo; f.tab=tab; return &f.fn; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; } My question is the following: is this a bug of GDC/LDC or is this the expected behaviour ? The second solution must always work but I'm unsure about the first one. Indeed, the specification says that a delegate shall not reference a stack parameter which is logical but it says nothing about function arguments.
Jan 31 2009
On Sat, Jan 31, 2009 at 5:36 PM, amaury pouly <amaury.pouly gmail.com> wrot= e:My question is the following: is this a bug of GDC/LDC or is this the exp=ected behaviour ? The second solution must always work but I'm unsure about= the first one. Indeed, the specification says that a delegate shall not re= ference a stack parameter which is logical but it says nothing about functi= on arguments. In D1, returning nested functions from the function that defined them is undefined behavior. If you're using DMD1 and it's working, you just got lucky. The compilers could detect this better, but more generally it's a problem of escape analysis and there will always be cases where they get it wrong. But in D2, it's legal and will create a closure. If you're using DMD2, that's why it's working.
Jan 31 2009
amaury pouly wrote:Hello, I have a little question about D: I want to have a function returning a delegate and more precisely a delegate literal that uses one of the arguments of the function. Here is an example: int delegate(int) test(int[] tab) { return (int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; }; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; }tools version: import tools.base, std.stdio; int delegate(int) test(int[] tab) { return tab /apply/ (int[] tab, int d) { int sum; foreach (i; tab) sum += i*d; return sum; }; } void main() { auto res = test([1,2,3,4,5,6])(4); writefln(res); }
Feb 01 2009
downs wrote:amaury pouly wrote:I was tempted to post mine out of sheer bloody-mindedness, except that it apparently doesn't work any more. Oh well, yours was about a million times safer, anyway. :P -- DanielHello, I have a little question about D: I want to have a function returning a delegate and more precisely a delegate literal that uses one of the arguments of the function. Here is an example: int delegate(int) test(int[] tab) { return (int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; }; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; }tools version: import tools.base, std.stdio; int delegate(int) test(int[] tab) { return tab /apply/ (int[] tab, int d) { int sum; foreach (i; tab) sum += i*d; return sum; }; } void main() { auto res = test([1,2,3,4,5,6])(4); writefln(res); }
Feb 01 2009
"amaury pouly" wroteHello, I have a little question about D: I want to have a function returning a delegate and more precisely a delegate literal that uses one of the arguments of the function. Here is an example: int delegate(int) test(int[] tab) { return (int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; }; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; } Of course this example is stupid but the idea is here. The point is that if I compile and run this code with DMD it works fine whereas it segfaults with GDC and LDC(LLVM D). I also know a fix for the segfault with both GDC and LDC: int delegate(int) test(int[] tab) { struct Foo { int[] tab; int fn(int d) { int sum; foreach(i;tab) sum+=i*d;// stupid computation return sum; } } Foo *f=new Foo; f.tab=tab; return &f.fn; } int main() { auto res=test([1,2,3,4,5,6])(4); return res; } My question is the following: is this a bug of GDC/LDC or is this the expected behaviour ? The second solution must always work but I'm unsure about the first one. Indeed, the specification says that a delegate shall not reference a stack parameter which is logical but it says nothing about function arguments.Expected behavior. Function arguments *are* stack parameters. Even though you are passing a parameter whose storage is defined in the main function (and technically, is allocated on the heap), the 'tab' parameter to test is a stack-based struct which contains the pointer to the array. When main calls the delegate, it overwrites that struct with new data, because the stack frame is reused, and therefore, it's anyones guess why it works on dmd. -Steve
Feb 02 2009