An aside: In case people want to crib the language, the Racket (formerly PLT Scheme) manual contains a warning about exactly this problem in the appended text (Section 3.1.2 of the "Inside: Racket C API" at http://docs.racket-lang.org/inside/im_memoryalloc.html#(part._im~3a3m~3astack) ). It shouldn't be hard to adapt the discussion to something appropriate for the OCaml manual: --------------------------------- The 3m collector needs to know the address of every local or temporary pointer within a function call at any point when a collection can be triggered. Beware that nested function calls can hide temporary pointers; for example, in scheme_make_pair(scheme_make_pair(scheme_true, scheme_false), scheme_make_pair(scheme_false, scheme_true)) the result from one scheme_make_pair call is on the stack or in a register during the other call toscheme_make_pair; this pointer must be exposed to the garbage collection and made subject to update. Simply changing the code to tmp = scheme_make_pair(scheme_true, scheme_false); scheme_make_pair(tmp, scheme_make_pair(scheme_false, scheme_true)) does not expose all pointers, since tmp must be evaluated before the second call toscheme_make_pair. In general, the above code must be converted to the form tmp1 = scheme_make_pair(scheme_true, scheme_false); tmp2 = scheme_make_pair(scheme_true, scheme_false); scheme_make_pair(tmp1, tmp2); and this is converted form must be instrumented to register tmp1 and tmp2. The final result might be { Scheme_Object *tmp1 = NULL, *tmp2 = NULL, *result; MZ_GC_DECL_REG(2); MZ_GC_VAR_IN_REG(0, tmp1); MZ_GC_VAR_IN_REG(1, tmp2); MZ_GC_REG(); tmp1 = scheme_make_pair(scheme_true, scheme_false); tmp2 = scheme_make_pair(scheme_true, scheme_false); result = scheme_make_pair(tmp1, tmp2); MZ_GC_UNREG(); return result; } Notice that result is not registered above. The MZ_GC_UNREG macro cannot trigger a garbage collection, so the result variable is never live during a potential collection. Note also that tmp1 andtmp2 are initialized with NULL, so that they always contain a pointer whenever a collection is possible. --------------------------------------------