35.5. The burden of garbage-collection upon the rest of CLISP

35.5.1. Lisp object invalidation
35.5.2. Managing Lisp objects in C
35.5.3. Run-time GC-safety checks
35.5.4. Memory protection

35.5.1. Lisp object invalidation

Every subroutine marked with can trigger GC or maygc may invoke garbage-collection. The garbage-collector moves all the CLISP non-immediate objects and updates the pointers. But the garbage-collector looks only at the STACK and not in the C variables. (Anything else would not be portable.) Therefore at every "unsafe" point, i.e. every call to such a subroutine, all the C variables of type object MUST BE ASSUMED TO BECOME GARBAGE. (Except for objects that are known to be unmovable, e.g. immediate objects or Subrs.) Pointers inside CLISP data (e.g. to the characters of a STRING or to the elements of a SIMPLE-VECTOR) become INVALID as well.

35.5.2. Managing Lisp objects in C

The workaround is usually to allocate all the needed CLISP data first and do the rest of the computation with C variables, without calling unsafe routines, and without worrying about garbage-collection.

Alternatively, you can save a lisp object on the STACK using macros pushSTACK() and popSTACK().

Warning

One should not mix these macros with functions which modify STACK in one statement because C may execute different parts of the statement out of order. E.g.,

pushSTACK(listof(4));

is illegal while

pushSTACK(STACK_0);

is legal.

35.5.3. Run-time GC-safety checks

Run-time GC-safety checking is available when you build CLISP with a C++ compiler, e.g.:

$ ./configure 'CC=g++' --with-debug build-g-gxx

When built like this, CLISP will abort when you reference GC-unsafe data after an allocation (which could have triggered a garbage-collection), and gdb will pinpoint the trouble spot.

Specifically, when CLISP is configured as above, there is a global integer variable alloccount and the object structure contains an integer allocstamp slot. If these two integers are not the same, the object is invalid. By playing with gdb, you should be able to figure out the precise spot where an allocation increments alloccount after the object has been retrieved from a GC-visible location.

35.5.4. Memory protection

Generational garbage-collector uses memory protection, so when passing pointers into the lisp heap to C functions, you may encounter errors (errno=EFAULT) unless you call handle_fault_range(protection,region_start,region_end) on the appropriate memory region. See files

src/unixaux.d
src/win32aux.d
modules/syscalls/calls.c
modules/rawsock/rawsock.c

for examples.


These notes document CLISP version 2.49.93+Last modified: 2018-02-19