[Gc] gc_typed.h allocation incompatible with GC_clear_roots()?

Henning Makholm Henning at octoshape.com
Tue Feb 5 07:34:08 PST 2008

Hello there,

Here is an interesting interaction between the use of
GC_clear_roots() to set a small root set explicitly, and the
typed allocation routines in typd_mlc.c. I was bitten by this
with the "stable" version 6.7 of the garbage collector, but from
a quick inspection of the 7.1alpha2 code it appears that it could
arise there, too.

I initialize the collector with

  struct { .... } globals = {0};
  int main(int argc, char** argv) {
    GC_no_dls = 1 ;
    GC_dont_precollect = 1 ;
    GC_add_roots((char*)&globals, (char*)(1+&globals));
    /* calls to GC_make_descriptor go here */
    /* rest of program goes here */

It turns out in my application that one of the GC_make_desrciptor()
bitmaps is so long and complex that GC_add_ext_descriptor() in
typd_mlc.c is called. Finding GC_ed_size to be 0, it allocates a
new array of ext_descr's *from collectable memory* and stores its
address in the GC_ext_descriptors variable.

However, GC_ext_descriptors is not in my explicit root set, so the
external descriptor array is reclaimed in the next collection. Once
I start using the large structures described by the bitmap, the
mark procedure finds zeroes in the external descriptor where ones
should have been; various stuff gets reclaimed prematurely and my
program crashes.

I am not *complaining* about this, as such - after all,
GC_clear_roots() is documented as "wizards only". But does not
look like intended behavior either. In particular, there does not
seem to be any general way for a client program that uses
GC_clear_roots() to re-add GC-internal roots such as
GC_ext_descriptors (indeed, if there are more than this one, the
linker might choose to scatter them all across the data section).

I can hack the collector to work around the problem in my particular
case - e.g. by using plain old malloc to allocate the ext_descr
array, since I know that I will call GC_make_descriptor only during
program startup and from a single thread. But that does not feel
like a general solution.

Perhaps there ought to be a complement to GC_arrays, containing
things that must *always* be roots? Or, if GC_ext_descriptors
happens to be the only "internal" root, GC_init_explicit_typing()
should just check if it in a known root segment, and add a one-word
segment otherwise?

Henning Makholm
OctoShape ApS

More information about the Gc mailing list