liveBook · Manning

Allocator API

As explained in Code Like a Pro in Rust

The allocator API is a Rust API for implementing and selecting custom memory allocators, including unstable interfaces available on the nightly release channel.

The allocator API lets a data structure use a custom allocator instead of the program’s global allocator. Use it when allocation needs to be controlled for a particular structure, such as for memory tracking, cross-language handoffs, or protected memory. It was nightly-only at the time described; the program-wide GlobalAlloc API was available on stable Rust. section 5.8 section 5.8.2

Implement the unsafe Allocator trait with allocate and deallocate. Both receive a Layout, which specifies size and minimum alignment. The trait supplies defaults for operations such as zeroed allocation, growth, and shrinking; default growth and shrinking allocate new memory, copy data, then deallocate the old block. Raw pointers and invalid pointer–layout pairs make the safety obligations consequential. section 5.8.1

Listing 5.11 Code for a pass-through allocator
#![feature(allocator_api)]

use std::alloc::{AllocError, Allocator, Global, Layout};
use std::ptr::NonNull;

pub struct PassThruAllocator;

unsafe impl Allocator for PassThruAllocator {
 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
     Global.allocate(layout)
 }
 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
     Global.deallocate(ptr, layout)
 }
}

Start with a pass-through implementation that delegates both required methods to Global. It isolates the Allocator interface before introducing platform allocation calls. section 5.8.1

Select an allocator for one vector

Construct a vector with `Vec::with_capacity_in(10, BasicAllocator)` to use a custom allocator for that data structure. The example pushes ten integers and prints the resulting vector. The accompanying malloc/free implementation is illustrative: its allocation path uses `layout.size()` and `NonNull::new_unchecked`, while Layout also carries alignment requirements. Check those requirements and pointer validity before adapting such code for production use. section 5.8.1

For sensitive data, an allocator can reserve page-aligned memory with extra regions before and after the active region, then return only the active slice. The protected-memory example uses `posix_memalign()` on UNIX or `VirtualAlloc()` on Windows, alongside platform memory-locking and protection calls. Deallocation must account for the original allocation and its surrounding regions. section 5.8.2

To compile allocator-API code, enable `#![feature(allocator_api)]` and use a nightly toolchain, for example with `cargo +nightly` or a `rustup` directory override. A published crate can gate the feature and its module behind a Cargo `nightly` feature, and mark that availability in rustdoc. Prefer stable GlobalAlloc when program-wide replacement meets the need; reserve the nightly allocator API for per-structure control that justifies its safety and portability work. section 3.7.1 section 3.7.2 section 5.8 section 5.8.1

How Code Like a Pro in Rust covers it

How deep it goes
Works through required Allocator methods, default operations, and unsafe pointer and layout obligations, then sketches a platform-specific protected allocator.
Examples
Demonstrates a Global pass-through allocator, a malloc/free allocator used with Vec, and a page-aligned protected-memory allocator.
What it assumes
Assumes familiarity with Rust traits, unsafe code, pointers, and conditional compilation rather than teaching their syntax from zero.
What you can do after
Build it from scratch for a data structure, while checking layout, pointer safety, platform requirements, and nightly availability.
How it connects
Connects Allocator to GlobalAlloc, Layout, Vec, conditional compilation, and protected memory.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Code Like a Pro in Rust. The section links point to the parts of the book it draws on.