Casting bigarray between different kinds, using ctypes, possible problems?

I have some code that allows to cast a bigarray between different kinds, using ctypes. The code is based on the earlier discussion here: Cast Bigarray kind

The code is:

(* t1 and t2 are ctypes kinds; t2_kind is a normal bigarray kind *)
let coerce_bigarray1 t1 t2 t2_kind arr = 
  Ctypes.bigarray_start Ctypes.array1 arr |> fun (pi:'t1 Ctypes.ptr) -> 
  Ctypes.(coerce (ptr t1) (ptr t2) pi) |> fun (pc:'t2 Ctypes.ptr) -> 
  Ctypes.bigarray_of_ptr (* this function forces C layout *) 
    Ctypes.array1 
    ((Bigarray.Array1.dim arr * Ctypes.(sizeof t1)) / Ctypes.(sizeof t2))
    t2_kind
    pc |> fun arr -> 
  arr

I began to get scared of this code. What if I cast from a bigarray of char to a bigarray of OCaml-native int? And what if the chars were such that one of the resulting ints was actually interpreted as a pointer? And what if I then accessed that value in the int bigarray? And GC kicked in? Would the GC interpret the integer as a pointer and wrongly follow it, causing a segfault?

(It turned out the segfault was actually a stack overflow, but I’m still worried about the situation described…)

I guess that, when accessing the int bigarray, there is some code to ensure that an array entry that resembles a pointer is actually interpreted as an int?

Hi,

A bigarray for the OCaml point-of-view (specially for the GC point-of-view) is an opaque value which exists into the C heap. Then, a small object exists into the OCaml heap to refer to this value - note that this object is associated to a finalizer to correctly free the value into the C heap.

That mostly means that the GC will never follows what you have into your bigarray. Then, the kind type express only how to transform a value into your bigarray into an OCaml value. For instance, if your bigarray is a char/int bigarray, it will use leaq to put the GC bit into the returned value. For values such as nativeint, it will, obviously (regardless some optimizations) allocates the nativeint into the OCaml heap and set it to the right value from the bigarray.

So you can safely say that the GC will never follow what it can find into your bigarray as an opaque value for its point of view.

2 Likes

Thank you for your reply. So, the bigarray is opaque, and accessing an element in an int bigarray will ensure that the element is treated as an int (by setting the lowest bit 0). Thanks, that makes sense.