Skip to main content

GlobalAllocator

Trait GlobalAllocator 

Source
pub unsafe trait GlobalAllocator:
    Allocator
    + Sync
    + 'static { }
🔬This is a nightly-only experimental API. (allocator_api #32838)
Expand description

An Allocator that can be registered as the standard library’s default through the #[global_allocator] attribute.

Types implementing this trait can be used as the default allocator for memory allocations through Box, Vec and the collection types. For instance, the System allocator implements this trait, and thus can be explicitly set as the default like so:

use std::alloc::System;

#[global_allocator]
static ALLOCATOR: System = System;

The Global allocator forwards all memory allocation requests to the static annotated with #[global_allocator]. Hence, Global does not implement GlobalAllocator itself, as that would lead to infinite recursion.

§Note to implementors

This trait is used to prevent the infinite recursion that would occur if the default allocator were to attempt to allocate memory through Global (and thus from itself).

When to implement this trait:

  • for custom global allocators that only use system memory allocation services.
  • for allocators that wrap another allocator that implements GlobalAllocator.

When not to implement this trait:

  • for wrappers of arbitrary allocators (which might end up being Global, leading to infinite recursion).

§Safety

In addition to the safety requirements of Allocator, global allocators are subject to some additional constraints:

  • It’s undefined behavior if global allocators unwind. This restriction may be lifted in the future, but currently a panic from any of these functions may lead to memory unsafety.

  • You must not rely on allocations actually happening, even if there are explicit heap allocations in the source. The optimizer may detect unused allocations that it can either eliminate entirely or move to the stack and thus never invoke the allocator. The optimizer may further assume that allocation is infallible, so code that used to fail due to allocator failures may now suddenly work because the optimizer worked around the need for an allocation. More concretely, the following code example is unsound, irrespective of whether your custom allocator allows counting how many allocations have happened.

    drop(Box::new(42));
    let number_of_heap_allocs = /* call private allocator API */;
    unsafe { std::hint::assert_unchecked(number_of_heap_allocs > 0); }

    Note that the optimizations mentioned above are not the only optimization that can be applied. You may generally not rely on heap allocations happening if they can be removed without changing program behavior. Whether allocations happen or not is not part of the program behavior, even if it could be detected via an allocator that tracks allocations by printing or otherwise having side effects.

§Re-entrance

When implementing a global allocator, one has to be careful not to create an infinitely recursive implementation by accident, as many constructs in the Rust standard library may allocate in their implementation. For example, on some platforms, std::sync::Mutex may allocate, so using it is highly problematic in a global allocator.

For this reason, one should generally stick to library features available through core, and avoid using std in a global allocator. A few features from std are guaranteed to not use #[global_allocator] to allocate:

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§