On Wed, Feb 3, 2016 at 12:01 PM, Christoph Höger <christoph.hoeger@tu-berlin.de> wrote:
Thanks for your reply,

Am 03.02.2016 um 12:48 schrieb Jeremie Dimino:
> void g(...) {
>   CAMLparam0();
>   CAMLlocal3(ml_t, ml_x, ml_g);
>   ...
>   CAMLreturn0;
> }

I tried this before, but it seemed like the GC would still write into
the arguments here. Is the semantics of CAMLparam0 that I might have
additional, unmanaged arguments?

CAMLparam0 is for when you have no [value] arguments but have some local [value] variables. CAMLlocalN must be preceded by a CAMLparamY, that's why you need the CAMLparam0.
 

> ​Note that &(user_data->g) must be a GC root as well. Are you
> registering &(user_data->g) with the GC in any way?

Good question. It _is_ an argument to a function on the other side of
the stack, so in principle it is alive, but could the GC move it?

​Yes, it should be alive. However I imagine that in the main C stub, you have something like this:

value blah(value g, ...)
{
  ...
  user_data->g = g;
  ...
}

So if the GC ends up moving [g], it needs to know that it must update [user_data->g] to point to the new location.

There are several solutions:

- if [user_data] only exists for the duration of the [blah] function call, I would suggest to change [user_data->g] to be a [value*] instead:

value blah(value g, ...)
{
​  CAMLparam1(g);​
​  ...
  user_data->g = &g;
  ...
}

- if it lives for longer, you need to register [user_data->g] as a global variable, as described in the manual (Rule 4 of http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html).

--
Jeremie