[plt-scheme] garbage collection questions

From: Dave Griffiths (dave at pawfal.org)
Date: Thu Feb 22 16:29:07 EST 2007

> At Wed, 21 Feb 2007 10:13:59 -0000 (GMT), "Dave Griffiths" wrote:
>> In a function extension, does the argv argument have to be protected from
>> garbage collector in _every_ function which can result in a scheme
>> allocation?
> Yes. In
>  Scheme_Object f(int argc, Scheme_object **argv) {
>    ...
>    scheme_do_something(...);
>    ...
>    ... argv[0] ...
>  }
> the caller of `f' may well have GC-registered a reference to the same
> array as `argv', in which case the array referenced by `argv' won't get
> collected during scheme_do_something(). But the array might get moved. So,
> `argv' definitely needs to be registered with the GC; that way, if
> scheme_do_something() causes the array to move, `argv' points to the new
> location on return.
>> Following on from this, is there documentation on which scheme api
>> functions contain an allocation call? Is it safer to just protect all
>> Scheme_Object pointers in every function extension regardless?
> The latter. The documentation says
>  Garbage collection can occur during any call into MzScheme or its
>  allocator, on anytime that MzScheme has control, except during
>  functions that are documented otherwise.
> Very few functions are documented otherwise. I think the vast majority of
> scheme_...() functions can, in fact, allocate.
> You can assume that macros named using ALL_CAPS_AND_UNDERLINES() do not
> allocate. For example, SCHEME_INTP() and SCHEME_INT_VAL() do not allocate.
> In "schemef.h", a number of functions are marked by XFORM_NON_GCING.
> That's a compilation hint to the xform tool, and is not actually meant as
> a part of the public API (i.e., don't rely on the annotations).

Sorry for the lack of RTFM on my part. That's great info though. I also
read your initial post about 3m after sending that email that helped a lot
to explain the underlying details and motivation:

>> Is there a way of running the garbage collector in a more deterministic
>> manner - ie, make it run in a slow "debug" mode, freeing all availible
>> memory at every opportunity (or is this what 3m does anyway) and then
>> making it possible to check (with valgrind or similar) for strangeness,
>> as a way of verifying extension code.
> Configure with --enable-compact, and then change the #define of CHECKS
> from 0 to 1 in "src/mzscheme/gc2/compact.c". This increases the number of
> consistency checks, but it's a long way for GCing at every
> opportunity (which would be prohibitively slow). You can change
> GROW_FACTOR to something closer to 1 to trigger more frequent
> collections.

I suspect that will do the trick for me - I had to spend a long time
tracking down some very occasional crashes caused by a simple
misunderstanding of the gc macros, anything to make potentially dodgy code
fail faster is good.

>> I also am having difficulty running tools like valgrind or gdb on
>> recent SVN versions of mzscheme.
> I don't know about Valgrind, but a common confusion with gdb under Linux
> is that you get a seg fault from 3m almost immediately on
> startup. That's because the GC uses page protection to implement write
> barriers.
> Tell gdb to ignore SIGSEGV:
>  (gdb) handle SIGSEGV nostop noprint
> and then continue. When there's a seg fault that doesn't look like a write
> to a GC-protected page, the GC's signal handler will call
> abort().

That's the one, thanks - I suspect there is a similar fix for valgrind,
I'll check it out.

Many thanks again,


Posted on the users mailing list.