Garbage collector collects live objects

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Dec 11 10:36:58 PST 2014


On 12/10/14 7:52 AM, Ruslan Mullakhmetov wrote:
> On Wednesday, 10 December 2014 at 08:46:12 UTC, Ruslan Mullakhmetov wrote:
>> yes. that was the mistake. also after fixing bug in Blk Attributes
>> printing i got more reasonable attrs
>>
>> for object blk: FINALIZE
>> for array of objects blk: NO_SCAN APPENDABLE
>>
>> this is sound good except for NO_SCAN.
>>
>> ...
>> the other question why this happens... try to debug more.
>
> I've done more dubugging.
>
> what i've found:
>
> initially array blk has only attrs APPENDABLE, but after some time this
> blk is shrinked and reallocated (moved) and then NO_SCAN attr appears.
>
>
> here the output of my extended logs:
>
> --------
> before tag: 1 len: 2 ptr: 103DD9058 root: 103DD8000:8192 attr: APPENDABLE
> after tag: 1 len: 3 ptr: 103A21DD0 root: 103A21DC0:64 attr: NO_SCAN
> APPENDABLE
> --------

My analysis so far:

1. The before/after makes sense except for the attribute and the offset. 
A realloc into a 64-byte block should NOT cause an offset of 16 bytes. I 
have found why it's happening, which is a bug, but not one that should 
cause the problem of setting the noscan bit (will file an issue on that).
2. In the array append code, the block attributes are obtained via 
GC.query, which has this code for getting the attributes:

https://github.com/D-Programming-Language/druntime/blob/master/src/gc/gc.d#L1792

Quoting from that function:

// reset the offset to the base pointer, otherwise the bits
// are the bits for the pointer, which may be garbage
offset = cast(size_t)(info.base - pool.baseAddr);
info.attr = getBits(pool, cast(size_t)(offset >> pool.shiftBy));

Which should get the correct bits. I suspected there was an issue with 
getting the wrong bits, but this code looks correct.

3. The runtime caches the block info for thread local data for append 
speed. A potential issue is that the attributes are cached from a 
previous use for that block, but the GC (and the runtime itself) SHOULD 
clear that cache entry when that block is freed, avoiding this issue. A 
potential way to check this is to assert in a debug build of druntime 
that the cached block info always equals the actual block info. Are you 
able to build a debug version of druntime to test this? I can give you 
the changes you should make. This would explain the great difficulty in 
reproducing the issue.

4. If your code is multi-threaded, but using __gshared, it can make the 
cache incorrect. Are you doing this?

But the cache is really the only possible place I can see where the bits 
are set incorrectly, given that you just verified the bits are correct 
before the append.

Can you just list the version of the compiler you are using? I want to 
make sure this isn't an issue that has already been fixed.

-Steve


More information about the Digitalmars-d-learn mailing list