# Finding GC problems in C bindings

**URL:** <https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453>\
**Category:** Learning\
**Tags:** ffi\
**Created:** [March 7, 2019, 2:19pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453 "2019-03-07T14:19:13Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [March 7, 2019, 2:19pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/1 "2019-03-07T14:19:13Z")

</div>

I have a C binding for a C library function where I suspect that it is not correct and causes a wrong value being returned in rare cases – which make me suspect it is GC related. Is there a general good strategy to find or trigger these kind of problems?  
For example, during development it could be helpful to check the integrity of the heap after every assignment in the C code or to force garbage collections.

Problems I am suspecting in the code below:

- `Field(v, 0)` should not be used but `caml_modify(&Field(v, 0), ...)` instead
- Use `caml_acquire_runtime_system()` around the actual library call

It would be nice to actually demonstrate that this is wrong and trigger a problem.

```auto
CAMLprim value
stub_statvfs(value filename)
{
    CAMLparam1(filename);
    CAMLlocal2(v, tmp);
    int ret;
    int i;
    struct statvfs buf;

    ret = statvfs(String_val(filename), &buf);

    if (ret == -1)
        uerror("statvfs", Nothing);

    tmp = caml_copy_int64(0);

    /*
     * Allocate the thing to return and ensure each of the fields is set
     * to something valid before attempting any further allocations 
     */
    v = alloc_small(11, 0);
    for (i = 0; i < 11; i++) {
        Field(v, i) = tmp;
    }

    Field(v, 0) = caml_copy_int64(buf.f_bsize);
    Field(v, 1) = caml_copy_int64(buf.f_frsize);
    Field(v, 2) = caml_copy_int64(buf.f_blocks);
    Field(v, 3) = caml_copy_int64(buf.f_bfree);
    Field(v, 4) = caml_copy_int64(buf.f_bavail);
    Field(v, 5) = caml_copy_int64(buf.f_files);
    Field(v, 6) = caml_copy_int64(buf.f_ffree);
    Field(v, 7) = caml_copy_int64(buf.f_favail);
    Field(v, 8) = caml_copy_int64(buf.f_fsid);
    Field(v, 9) = caml_copy_int64(buf.f_flag);
    Field(v, 10) = caml_copy_int64(buf.f_namemax);

    CAMLreturn(v);
}

```

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [March 7, 2019, 2:44pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/2 "2019-03-07T14:44:01Z")

</div>

> [@lindig](#):
>
> Is there a general good strategy to find or trigger these kind of problems?

I had quite sucess in the past by simply calling `Gc.full_major ()` after any binding call, usually a segfault would immediately occur after the offending one.

> [@lindig](#):
>
> `Field(v, 0)` should not be used

That looks indeed suspicious the idomatic way (cf [rule 3](https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec442)) of doing this would be:

```auto
v = caml_alloc (11, 0); 
Store_field (v, 0, caml_copy_int64(buf.f_bsize));
...
CAMLreturn (v);

```

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [March 7, 2019, 2:53pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/3 "2019-03-07T14:53:54Z")

</div>

> [@dbuenzli](#):
>
> That looks indeed suspicious

More precisely I would say that rule 6 is being violated here.

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [March 7, 2019, 3:19pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/4 "2019-03-07T15:19:15Z")

</div>

Since a field already has a valid value, does this not force to use `caml_modify` as mandated by [Rule 6](https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec441)?

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [March 7, 2019, 3:26pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/5 "2019-03-07T15:26:17Z")

</div>

I guess so and anyways this:

> " _Field(v, n) = w;_ _is safe only if v is a block newly allocated by caml\_alloc\_small; that is, if no allocation took place between the allocation of v and the assignment to the field. In all other cases, never assign directly._

is strongly violated here since each of the caml\_copy\_int64 allocates.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [March 7, 2019, 3:27pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/6 "2019-03-07T15:27:36Z")

</div>

You may also find it instructrive to see how `Unix.stat` is implemented in OCaml itself:

> <https://github.com/ocaml/ocaml/blob/9dda8fae43b05fbbde5c1435885e8a9eaec54eeb/otherlibs/unix/stat.c#L50>

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [March 7, 2019, 3:32pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/7 "2019-03-07T15:32:08Z")

</div>

Indeed, this would provide a template. It also uses `caml_enter_blocking_section()` which is missing in the code I have. When is it safe to omit it?

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [March 7, 2019, 3:49pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/8 "2019-03-07T15:49:38Z")

</div>

> [@lindig](#):
>
> When is it safe to omit it?

It’s always safe_r_ to omit. It’s better to add if the bracketed C code may be long and/or may block _and_ is guaranteed not to interact with the OCaml runtime system.

Read the details [in the manual](https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec478).

---

<div class="post-metadata">

**Author:** ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)\
**Post date:** [March 11, 2019, 2:55pm UTC](https://discuss.ocaml.org/t/finding-gc-problems-in-c-bindings/3453/9 "2019-03-11T14:55:34Z")

</div>

> [@lindig](#):
>
> Since a field already has a valid value, does this not force to use `caml_modify` as mandated by [Rule 6](https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec441)?

If you mean force the use of `caml_modify` in place of the use of `Store_field`, then I think no. `Store_field` calls `caml_modify`:

```auto
#define Store_field(block, offset, val) do{ \
  mlsize_t caml__temp_offset = (offset); \
  value caml__temp_val = (val); \
  caml_modify (&Field ((block), caml__temp_offset), caml__temp_val); \
}while(0)

```
