finalise f v
registers f
as a finalisation function for v
. v
must be heap-allocated. f
will be called with v
as argument at some point between the first time v
becomes unreachable (including through weak pointers) and the time v
is collected by the GC. Several functions can be registered for the same value, or even several instances of the same function. Each instance will be called once (or never, if the program terminates before v
becomes unreachable).
The GC will call the finalisation functions in the order of deallocation. When several values become unreachable at the same time (i.e. during the same GC cycle), the finalisation functions will be called in the reverse order of the corresponding calls to finalise
. If finalise
is called in the same order as the values are allocated, that means each value is finalised before the values it depends upon. Of course, this becomes false if additional dependencies are introduced by assignments.
In the presence of multiple OCaml threads it should be assumed that any particular finaliser may be executed in any of the threads.
Anything reachable from the closure of finalisation functions is considered reachable, so the following code will not work as expected:
let v = ... in Gc.finalise (fun _ -> ...v...) v
Instead you should make sure that v
is not in the closure of the finalisation function by writing:
let f = fun x -> ... let v = ... in Gc.finalise f v
The f
function can use all features of OCaml, including assignments that make the value reachable again. It can also loop forever (in this case, the other finalisation functions will not be called during the execution of f, unless it calls finalise_release
). It can call finalise
on v
or other values to register other functions or even itself. It can raise an exception; in this case the exception will interrupt whatever the program was doing when the function was called.
finalise
will raise Invalid_argument
if v
is not guaranteed to be heap-allocated. Some examples of values that are not heap-allocated are integers, constant constructors, booleans, the empty array, the empty list, the unit value. The exact list of what is heap-allocated or not is implementation-dependent. Some constant values can be heap-allocated but never deallocated during the lifetime of the program, for example a list of integer constants; this is also implementation-dependent. Note that values of types float
are sometimes allocated and sometimes not, so finalising them is unsafe, and finalise
will also raise Invalid_argument
for them. Values of type 'a Lazy.t
(for any 'a
) are like float
in this respect, except that the compiler sometimes optimizes them in a way that prevents finalise
from detecting them. In this case, it will not raise Invalid_argument
, but you should still avoid calling finalise
on lazy values.
The results of calling String.make
, Bytes.make
, Bytes.create
, Array.make
, and Stdlib.ref
are guaranteed to be heap-allocated and non-constant except when the length argument is 0
.