A bug in my code

bearophile bearophileHUGS at lycos.com
Sun Sep 7 04:48:57 PDT 2008


Manfred_Nowak:
> Sorrily it might be correct only at the surface. In the deeper grounds 
> your coding might be lead by some wrong assumptions on the semantics of 
> the interface to the GC.
> You are setting the attribute of `hasNoPointers' for each and every 
> memory block you `malloc'. But this is not true, because with the 
> assignment above you are introducing a pointer into that area, without 
> calling `hasPointers'.
> This means that on the nextrun of `FullCollect' close to no elements of 
> the list are referenced anymore: they all get collected, except `head' 
> and `tail' ofcourse.

You are right, that's the bug, thank you very much. I am used with languages where you have no GC, and you do everything by yourself, and high-level languages with GC where the GC works by itself. In the D code like that you have to interact with the GC a bit more closely :-)
If not already present somewhere, I think D newbies will enjoy a small tutorial on such GC usage.

This is the line of code that creates a new Block, it calls hasNoPointers() internally:
auto new_block = cast(Block*)mem_alloc(Block.sizeof);

The best way to solve the bug is to allocate that struct normally:
auto new_block = new Block;
So the GC knows where the GC pointers are.
(Later I have realized that for this problem an even better solution is to not use a linked list at all, and append the block structs into a growing dynamic array, where the structs now have just two fields: a len and a pointer to the block data).


But I'm trying to learn to use the GC, not just to debug this little experimental program. This is an alternative solution, that works, but I don't trust/like this much because I *think* the GC may scan all the struct fields for possible pointers, even the 'len' (an integer) one (if that idea of mine is wrong then please tell me):
auto new_block = cast(Block*)mem_alloc(Block.sizeof);
hasPointers(new_block);


So I have tried this, I have written this assuming that addRoot() adds a single pointer to the GC collected pool, but this last solution doesn't work, I don't know why:
auto new_block = cast(Block*)mem_alloc(Block.sizeof);
new_block.data = cast(int*)mem_alloc(nints * int.sizeof);
new_block.len = nints;
new_block.next = null;
addRoot(new_block.next);
addRoot(new_block.data);

Bye and thank you,
bearophile


More information about the Digitalmars-d-learn mailing list