global_allocator
The tracking issue for this feature is: #27389
Rust programs may need to change the allocator that they're running with from
time to time. This use case is distinct from an allocator-per-collection (e.g. a
Vec
with a custom allocator) and instead is more related to changing the
global default allocator, e.g. what Vec<T>
uses by default.
Currently Rust programs don't have a specified global allocator. The compiler
may link to a version of jemalloc on some platforms, but this is not
guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed
to use the "system allocator" which means something like malloc
on Unixes and
HeapAlloc
on Windows.
The #[global_allocator]
attribute, however, allows configuring this choice.
You can use this to implement a completely custom global allocator to route all
default allocation requests to a custom object. Defined in RFC 1974 usage
looks like:
#![feature(global_allocator, allocator_api, heap_api)] use std::alloc::{GlobalAlloc, System, Layout, Opaque}; use std::ptr::NonNull; struct MyAllocator; unsafe impl GlobalAlloc for MyAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut Opaque { System.alloc(layout) } unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) { System.dealloc(ptr, layout) } } #[global_allocator] static GLOBAL: MyAllocator = MyAllocator; fn main() { // This `Vec` will allocate memory through `GLOBAL` above let mut v = Vec::new(); v.push(1); }
And that's it! The #[global_allocator]
attribute is applied to a static
which implements the Alloc
trait in the std::alloc
module. Note, though,
that the implementation is defined for &MyAllocator
, not just MyAllocator
.
You may wish, however, to also provide Alloc for MyAllocator
for other use
cases.
A crate can only have one instance of #[global_allocator]
and this instance
may be loaded through a dependency. For example #[global_allocator]
above
could have been placed in one of the dependencies loaded through extern crate
.
Note that Alloc
itself is an unsafe
trait, with much documentation on the
trait itself about usage and for implementors. Extra care should be taken when
implementing a global allocator as well as the allocator may be called from many
portions of the standard library, such as the panicking routine. As a result it
is highly recommended to not panic during allocation and work in as many
situations with as few dependencies as possible as well.