A bug in my code

Jarrett Billingsley jarrett.billingsley at gmail.com
Sun Sep 7 11:11:09 PDT 2008


On Sun, Sep 7, 2008 at 12:59 PM, bearophile <bearophileHUGS at lycos.com> wrote:
> Jarrett Billingsley:
>
>> ..Or just, you know, arrays.  Since that's exactly what they are.
>
> Right, but I don't want to use them because dynamic arrays always set their memory to .init. The point of that data structure is to have a fast allocation too (it's not necessary to clean it if you know how many items you are using and the items don't contain a GC-managed pointer (see at the bottom of this post)).

The array is only initialized when you allocate it.  So, just allocate
a raw block of uninitialized memory and slice it to get an array.  I'm
not so much trying to say that using a struct is the wrong way to do
it, but rather that it's pointless to use a struct { int* data, size_t
length } when that's _precisely_ what an array is, and arrays give you
nicer syntax.

> Uhm... I don't understand fully: do you mean roots don't become deleted when they have nothing that points to them?
> The docs say:
> "Roots are references to memory allocated by the collector that are maintained in memory outside the collector pool."

I think what you should be using instead is addRange.  addRoot more or
less tells the GC "never collect memory referenced by this pointer",
but it doesn't actually scan the memory _pointed to_ by the roots for
pointers.  addRange tells the GC "scan this range of memory for
pointers", which is what you want to tell the GC to do for Blocks.
But then you run into another problem -- addRange and removeRange are
terribly inefficient.  So.. stop making things hard on yourself ;)

> If roots don't become deleted when they have nothing that points to them then I don't want to use roots in my code. What's the way to add a pointer to the pool of pointers scanned by the GC that become deleted when nothing points to it? :-)
> (In this data structure I can remove roots manually during inside the ~this(), but I'd prefer to not have to).

Uh, you don't have to do anything special.  You just use "new" to
allocate a block of memory, and if it could contain pointers, and that
block of memory is transitively accessible from the
stack/registers/globals, then any pointers it contains will be
scanned, and any memory pointed to by it will not be freed.

> I'm trying to learn how to use the GC because I'd like to create quite more complex data structures.

I think you're making things way more complicated than they need to be.

> I have created a recursive template that tells if a data structure contains a reference. If they aren't present, I don't need to set memory to their .init. My template is not perfect, because it doesn't tell apart normal references from GC-references, so if you create a stack (ArrayBuilder) of not-GC pointers, they become set to null even if they don't need such thing, wasting a bit of time. On the other hand the only way to tell if a reference is GC-managed is to use (at runtime) TypeInfo.flags(), but someone has told that it's buggy (Phobos).

You are obsessed with performance.  Please stop it, it's not everything.

>>You don't need to muck with the GC really at all in this case, other than to set the allocated arrays as having no pointers.<
>> ...
>> auto d = new int[nints];
>> hasNoPointers(d.ptr);
>> ...
>
> That hasNoPointers is quite useless, because the GC knows that 'd' is a dynamic array of ints, so it knows its memory doesn't contain GC-managed pointers. Isn't muching with the GC nice? :-)

Ah.

Well, you can leave it in if you replace "new int[nints]" with
"cast(int[])std.gc.malloc(nints * int.sizeof)".  That'll get you an
uninitialized array, but I think you still need to explicitly set the
"has no pointers" flag.


More information about the Digitalmars-d-learn mailing list