[Issue 8774] 2.059 worked 2.060 does not: nested delegate memory corruption

d-bugmail at puremagic.com d-bugmail at puremagic.com
Wed Dec 26 14:22:52 PST 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8774



--- Comment #26 from Dmitry Olshansky <dmitry.olsh at gmail.com> 2012-12-26 14:22:48 PST ---
(In reply to comment #21)
> OK I can accept that map delivers an iterable but not a sequence, so to create
> a sequence application of array is needed.

It's not exactly  an iterable or sequence, it's a lazy computation represented
as a range. The key point is that it doesn't even attempt to store results
somewhere nor avoid recomputation on demand.

> This would imply though that 2.059 →
> 2.060 introduces an undocumented breaking change – albeit a good one correcting
> a bug.
> 

The only case I think it might have worked previously is the following chain of
"events":
1. map used to cache the first entry (and maybe the last) (AFAIK it was in
2.057 or earlier)
2. then 1 thread out of pack is indeed the one that can be joined, the others
are these that are newely created and not started. (if both front & back - then
2 threads)
3. the join somehow worked on not yet started threads.
4. the join then waited on only one thread (or maybe 2).
5. by sheer luck to the moment of printing stuff all threads arrive completed
(since printing takes some time and is interlocked there is plenty of chance
for other threads to finish the work)

So... can you print the addresses of threads (in both start & join loops) in
2.059 where it used to work. It's intriguing to see if this guess is on spot
and what forces are at work there.

> Having i work and ii not work implies the whole closure capture mechanism in
> 2.059 → 2.060 underwent breaking change. The question then is which closure
> semantics are correct, indeed whether delegates are required to create
> closures.

No, I suspect you are confusing these 2 cases:
foreach(i; x..y)
{
   threads ~= delegate (){ 
       //use i here
   }
}

vs

threads = map!( (int i){ use i here ... })(...);

Note that in second case 'i' is a parameter passed to a delegate that is in
turn passed by alias to map. Thus 'i' is unique for every stack frame (or call)
of the said delegate.

In the first case 'i' is tied to the same variable on the stack frame for each
delegate create.

Semantically there are 2 rules:
- context capture happens on delegate creation
- during context capture everything in the current function scope is captured
by ref (behind the scenes rather the whole is captured by a single ref to a
stack frame)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list