Dealing with naked pointers from OCaml is notoriously difficult. As you found out, you have no good ways of controlling GC cycles, and to limit bad effects of that. Also, there is a dangling pointer problem - essentially the naked pointer can be mistaken as heap pointer between the time the memory has been freed and the naked pointer is set to null. Note that this aspect is practically impossible to do right from OCaml code, and even in a C function it is easy to get wrong, resulting in random crashes that occur infrequently. For these reasons naked pointers are strongly discouraged. The way to go is to wrap pointers into custom blocks (http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec458), and to do all pointer management in C. Gerd Am Dienstag, den 12.01.2016, 09:12 +0000 schrieb Neuhaeusser, Martin: > Dear all, > > during our work on some SMT solver bindings, a couple of question came up regarding the behavior of the OCaml garbage collector (see also https://github.com/Z3Prover/z3/issues/411). Assume we have defined a record type containing a native pointer to some object from an external C-DLL: > > type ocaml_record = { > native_ptr np; > [... some more fields ...] > } > > When creating an ocaml_record, we register a finalizer that makes the C library dispose the data belonging to the native pointer once the GC collects the OCaml record value: > > let f ocaml_record = NativeLib.dispose ocaml_record.np > > let create [...] = > let new_ocaml_record = { ... } in > Gc.finalise f new_ocaml_record; > new_ocaml_record > > When calling one of the C-stubs, we pass the native pointer from the OCaml record value: > > let get_native_pointer ocaml_record = ocaml_record.np > > NativeLib.native_function (get_native_pointer ocaml_record) > > However, this has the problem that if ocaml_record has become otherwise unreachable, the GC might collect ocaml_record directly after evaluating (get_native_pointer ocaml_record), triggering the finalizer which disposes the data pointed at by ocaml_record.native_ptr. The successive call to NativeLib.native_function (i.e. the C-stub) results in a segfault, as it tries to access data that has previously been freed by the finalizer. > > I assume this is a common problem in writing interfaces to C libraries. If so, is there a preferred way how to tackle it? > Two approaches that came to my mind are > > 1. One could design the C-stubs such that they accept values of type ocaml_record and extract the native pointer within the C stub. In the C-stubs, the GC must not collect an item that has been "pinned" by the CAMLparamX macros, right? > 2. One could invent some function that takes an ocaml_record, but does nothing with it and whose calls do not get optimized away by the compiler... Evaluating such a function after the call to NativeLib.native_function would prevent the GC from collecting ocaml_record. However, this feels like a very ugly hack. > > Are there any better ideas? Any help and suggestions are highly appreciated. > > Best, > Martin > -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany gerd@gerd-stolpmann.de My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------