[Issue 927] writefln() is duplicating values for parameters supplied

Kevin Bealer kevinbealer at gmail.com
Sun Feb 4 15:03:09 PST 2007


Frits van Bommel wrote:
> d-bugmail at puremagic.com wrote:
>> ------- Comment #5 from rmann-d-lang at latencyzero.com  2007-02-03 21:41 
>> -------
>> I was reading somewhere that the compiler could put the stack frame on 
>> the heap
>> in situations like that, so that it would actually work to reference 
>> local
>> variables.
> 
> Perhaps, but until it does this should be an error. Or at least a 
> warning (I know, Walter doesn't like those).
> Returning local arrays & delegates are probably two of the most common 
> bugs seen on d.D.learn.

I'm not against producing an error in the cases where the compiler can 
detect this cleanly.  I expect there to be some cases which are easy and 
some which are thorny (but I don't really know).

I think compilers for languages like ruby put all the stack frames on 
the heap, and this issue is solved completely, but it's one of those 
features that causes the performance to drop sharply when used.  I seem 
to remember that Perl allows more of this than D, and Ruby does more 
than Perl.  Java falls somewhere in this spectrum.  This was the 
explanation for why you can't build a Ruby (or was it perl?) interpreter 
that works under the JVM, because the JVM doesn't do stacks this way and 
can't be made to.  But I don't have the link to this and don't remember 
the exact details.

I guess the implied next step is to allocate a copy of the relevant 
portions of the stack to wrap up the delegate in question.  In other 
words, implement a partial version of the closure mechanism for these 
cases.  I don't know how well this would work, but these are my thoughts:

1. It would absolutely slaughter performance to do it every time -- the 
foreach() mechanism uses a delegate, so looping from 1 to 1_000_000,
would incur 1 million allocations.  So it'd have to be selective.

2. In a lot of cases you want the delegate to modify stuff in the stack 
frame (most foreach loops compute a value that goes in a variable that 
outlives the foreach), so it would have to be a copy of the stack frame 
when returning the delegate but use the *real* stack frame when not 
returning it.

If you return the delegate up the call stack *and* use it in a downward 
direction, then the entire function would need to work with a garbage 
collected stack frame (or a gc portion of a stack frame).  This is 
probably rare.

All of this can be done now, if you put the important stuff in a class 
and return a delegate to a method of that class.  But it requires 
programmer intervention of course.

I think that to make this both (as) efficient (as possible) *and* work 
as expected everywhere, would require a level of analysis similar to 
checking const correctness in C++ (you need to know where every delegate 
might go and what stuff it uses from the stack).  And when you are done 
you have a feature that is going to be slow enough to use that I suspect 
most people will shy away from it most of the time.

The same issues apply to returning a reference to any local variable, 
which I think is generally permitted in C (though gcc does warn about 
this with -Wall).

Kevin


More information about the Digitalmars-d-bugs mailing list