question about the implementation of Variant

Kapps via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Jan 4 09:34:47 PST 2016


On Monday, 4 January 2016 at 09:13:25 UTC, Jonathan M Davis wrote:
> On Monday, January 04, 2016 07:30:50 aki via 
> Digitalmars-d-learn wrote:
>> But wait, how does GC detect there still be a live reference to
>> the object Foo?
>> Because store is just a fix sized array of bytes.
>> ubyte[size] store;
>> GC cannot be aware of the reference, right?
>
> As I understand it, the GC doesn't actually care about whether 
> something is a pointer when it tries to figure out whether 
> something refers to something - or at least, it'll treat 
> integers as if they were pointers so that if you tried to do 
> something like
>
>     size_t i;
>     {
>         auto p = new int(5);
>         i = cast(size_t)p;
>     }
>     // GC will not collect p even if it runs now
>
> then the fact that i matches the value of the address that p 
> points to is enough for the GC to not collect the memory 
> pointed to by p, even if there are no longer any pointers 
> referring to it. This prevents problems when you do stuff like 
> cast pointers to integers to store their values (which normally 
> is crazy but on rare occasions makes sense). The downside is 
> that the GC then has to treat all integers as if they were 
> pointers, so if you have an integer whose value happens to 
> match that of a memory address in GC-allocated memory (a so 
> called false pointer), then that memory won't be freed, even if 
> nothing is really pointing to it anymore. Fortunately, however, 
> false pointers are primarily limited to 32-bit programs, and 
> 64-bit programs don't have that problem because of how large 
> their address space is (but 32-bit programs which allocate most 
> of their address space can definitely run into problems where 
> memory that should be freed isn't thanks to false pointers).
>
> - Jonathan M Davis

That's only because we don't have a precise garbage collector and 
can't be relied upon. It's more of a bug / limitation rather than 
something to actually use.

In the case of std.variant, it's not just byte[size] store, it's 
actually a union:

union
{
     ubyte[size] store;
     // conservatively mark the region as pointers
     static if (size >= (void*).sizeof)
         void*[size / (void*).sizeof] p;
}

Which tells the garbage collector that it may be pointers there, 
making it valid even for precise garbage collectors (which would 
have to conservatively handle such a union).


More information about the Digitalmars-d-learn mailing list