All Caml objects are represented by the C type value, defined in the include file caml/mlvalues.h, along with macros to manipulate values of that type. An object of type value is either:
Integer values encode 31-bit signed integers (63-bit on 64-bit architectures). They are unboxed (unallocated).
Blocks in the heap are garbage-collected, and therefore have strict structure constraints. Each block includes a header containing the size of the block (in words), and the tag of the block. The tag governs how the contents of the blocks are structured. A tag lower than No_scan_tag indicates a structured block, containing well-formed values, which is recursively traversed by the garbage collector. A tag greater than or equal to No_scan_tag indicates a raw block, whose contents are not scanned by the garbage collector. For the benefits of ad-hoc polymorphic primitives such as equality and structured input-output, structured and raw blocks are further classified according to their tags as follows:
|Tag||Contents of the block|
|0 to No_scan_tag-1||A structured block (an array of Caml objects). Each field is a value.|
|Closure_tag||A closure representing a functional value. The first word is a pointer to a piece of code, the remaining words are value containing the environment.|
|String_tag||A character string.|
|Double_tag||A double-precision floating-point number.|
|Double_array_tag||An array or record of double-precision floating-point numbers.|
|Abstract_tag||A block representing an abstract datatype.|
|Custom_tag||A block representing an abstract datatype with user-defined finalization, comparison, hashing, serialization and deserialization functions atttached.|
Any word-aligned pointer to an address outside the heap can be safely cast to and from the type value. This includes pointers returned by malloc, and pointers to C variables (of size at least one word) obtained with the `&' operator.
Caution: if a pointer returned by malloc is cast to the type value and returned to Caml, explicit deallocation of the pointer using free is potentially dangerous, because the pointer may still be accessible from the Caml world. Worse, the memory space deallocated by free can later be reallocated as part of the Caml heap; the pointer, formerly pointing outside the Caml heap, now points inside the Caml heap, and this can confuse the garbage collector. To avoid these problems, it is preferable to wrap the pointer in a Caml block with tag Abstract_tag or Custom_tag.