[Gc] Ignoring certain pointers in C++?

Petter Urkedal urkedal at nbi.dk
Fri Apr 20 10:33:07 PDT 2007


On 2007-04-20, Johann 'Myrkraverk' Oskarsson wrote:
> Bruce Hoult <br... at hoult.org> writes:
> 
> > On 4/20/07, Johann 'Myrkraverk' Oskarsson <myrkraverk at yahoo.com> wrote:
> >> Hi,
> >>
> >> I'll admit that I'm mostly playing with Gc, or plain using it by
> >> deriving from the gc class.
> >>
> >> Now, in order not to have duplicates of a certain type of object I
> >> constructed an object factory that returns a pointer to an already
> >> existing one, if it's already been allocated with those parameters.

I think what you are doing is essentially hash-consing (named due to its
LISP heritage).  Usually this is done by storing objects in a hash-map
keyed on the whole allocated object (aka hash-set).  If you also
recursively hash-cons all contained pointers, then the hash-function is
cheap and does not need to follow pointers.

> >> For this I hold a list of all objects of this kind, so they are
> >> perpetual.  Is it possible to tell Gc not to check this pointer
> >> collection when collecting?  I'm currently using a link list for these
> >> pointers, so I would need to be notified when an object is reclaimed
> >> if I keep that structure.

You can store pointers in atomic memory (GC_MALLOC_ATOMIC) tell the
collector not to scan them.  (If you want to avoid the extra indirection
and memory fragments the may cause, a trick is to do a bitwise-not of
the pointers so that the collector does not recognise them.)

And yes, in addition you always need some kind of feedback from the
collector when doing this, whether you use lists or hash maps.  That's
the tricky part, especially if you also need good performance.

> > register_disappearing_link is probably the way to go for this.  Just
> > make sure that your pointer collection does something sensible when it
> > finds that what used to be a pointer to an object is now null -- e.g.
> > deletes the linked list node.
> 
> I played with it, and tried to be sure my code handles it, but I'm not
> at all too sure how I test it.  I'm currently using
> GC_register_disappearing_link() but according to gc.h, it's better to
> use GC_general_register_disappearing_link(); however, it says:

I agree that GC_GENERAL_REGISTER_DISAPPEARING_LINK is probably the best
here.  An alternative is to use GC_REGISTER_FINALIZER_NO_ORDER and have
the finaliser remove the node from the list.  This saves you from
dealing with NULL pointers, but then you have to be careful about
locking the container without causing deadlock, considering that
finalisers may be running in the same thread as the code which creates
the objects.   (I use a third option which requires a patch to the
collector, but with fall-back to disappearing links when the collector
is unpatched.)

>         /* Obj must be a pointer to the first word of an object */
>         /* we allocated.  It is unsafe to explicitly deallocate */
>         /* the object containing link.  Explicitly deallocating */
>         /* obj may or may not cause link to eventually be       */
>         /* cleared.                                             */
> 
> So, while I can pretty easily "fake" the circumstances by deleting the
> object and clearing the link, I have not managed to come up with a
> scenario where the Gc actually reclaims an object and therefore
> convince myself that the method is sound.
> 
> Yes, I know it's not unusual for small test applications not to have
> any GCing taking place, but does anyone have or know of a scenario I
> can try?

A method to test the collector is loop over randomised tests and assign
to a limited-sized array in order to retain only some of the objects:

#define ARRAY_SIZE  100000
#define ALLOC_COUNT 400000

int main()
{
    void *arr[ARRAY_SIZE];
    memset(arr, 0, sizeof(arr));
    for (i = 0; i < ALLOC_COUNT; ++) {
	j = lrand48() % ARRAY_SIZE;
	arr[j] = create_random_object(i, j);
    }
}

At the end, you can check that the objects in the array are consistent,
e.g. if you wrote the integer j somewhere in each object, you can check
that the object was not overwritten.  Keep counters of discovered NULL
pointers, etc, and print out at the end so see that things look sane.


More information about the Gc mailing list