Expand description
An opt-in #[global_allocator] backed by the BEAM allocator.
EnifAlloc routes every Rust heap allocation in the NIF library through
enif_alloc/enif_free. This matters for hot code upgrade: enif_free is
the one free path that is valid across two independently compiled builds of
the library (a stable C ABI), whereas Rust’s default allocator is
build-private. Routing allocations through the VM allocator is therefore a
building block for carrying state across the upgrade boundary safely (see
docs/UPGRADE.md).
§Why direct-linked, not dlsym
The rest of otter resolves enif_* symbols at run time with dlsym (via
the enif_ffi crate). A global allocator cannot: it may be called for the very
first Rust allocation, before any initialization code runs, so it must not
depend on a resolution step that itself allocates. Instead this module
direct-links the two functions it needs as extern "C". The BEAM
exports them, and the dynamic linker binds them when the NIF .so is
dlopen’d (RTLD_NOW) — before nif_init, before any Rust code. There is
no catch-22.
§Inert until you opt in
EnifAlloc is always available, but it is referenced — and therefore
pulls in the direct-linked enif_alloc/enif_free symbols — only when you
install it as the global allocator with enif_global_allocator!. Until
then dead-code elimination drops it, so otter still links into ordinary,
non-BEAM binaries (its own cargo test, doc builds, etc.).
Once you do install it, those two symbols are undefined in the object file
and resolved only when the BEAM loads the .so — so a crate that invokes
the macro links only as a NIF cdylib hosted by the BEAM, never as an
ordinary executable.
Structs§
- Enif
Alloc - A
GlobalAllocbacked by the BEAM allocator (enif_alloc/enif_free).