]> git.proxmox.com Git - rustc.git/blame - src/doc/book/custom-allocators.md
Imported Upstream version 1.7.0+dfsg1
[rustc.git] / src / doc / book / custom-allocators.md
CommitLineData
b039eaaf
SL
1% Custom Allocators
2
3Allocating memory isn't always the easiest thing to do, and while Rust generally
4takes care of this by default it often becomes necessary to customize how
5allocation occurs. The compiler and standard library currently allow switching
6out the default global allocator in use at compile time. The design is currently
7spelled out in [RFC 1183][rfc] but this will walk you through how to get your
8own allocator up and running.
9
10[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1183-swap-out-jemalloc.md
11
12# Default Allocator
13
14The compiler currently ships two default allocators: `alloc_system` and
15`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
9cc50fc6 16are normal Rust crates and contain an implementation of the routines to
b039eaaf
SL
17allocate and deallocate memory. The standard library is not compiled assuming
18either one, and the compiler will decide which allocator is in use at
19compile-time depending on the type of output artifact being produced.
20
21Binaries generated by the compiler will use `alloc_jemalloc` by default (where
22available). In this situation the compiler "controls the world" in the sense of
23it has power over the final link. Primarily this means that the allocator
24decision can be left up the compiler.
25
26Dynamic and static libraries, however, will use `alloc_system` by default. Here
27Rust is typically a 'guest' in another application or another world where it
28cannot authoritatively decide what allocator is in use. As a result it resorts
29back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
30memory.
31
32# Switching Allocators
33
34Although the compiler's default choices may work most of the time, it's often
35necessary to tweak certain aspects. Overriding the compiler's decision about
36which allocator is in use is done simply by linking to the desired allocator:
37
38```rust,no_run
39#![feature(alloc_system)]
40
41extern crate alloc_system;
42
43fn main() {
44 let a = Box::new(4); // allocates from the system allocator
45 println!("{}", a);
46}
47```
48
49In this example the binary generated will not link to jemalloc by default but
50instead use the system allocator. Conversely to generate a dynamic library which
51uses jemalloc by default one would write:
52
53```rust,ignore
54#![feature(alloc_jemalloc)]
55#![crate_type = "dylib"]
56
57extern crate alloc_jemalloc;
58
59pub fn foo() {
60 let a = Box::new(4); // allocates from jemalloc
61 println!("{}", a);
62}
63# fn main() {}
64```
65
66# Writing a custom allocator
67
68Sometimes even the choices of jemalloc vs the system allocator aren't enough and
69an entirely new custom allocator is required. In this you'll write your own
70crate which implements the allocator API (e.g. the same as `alloc_system` or
71`alloc_jemalloc`). As an example, let's take a look at a simplified and
72annotated version of `alloc_system`
73
74```rust,no_run
75# // only needed for rustdoc --test down below
76# #![feature(lang_items)]
77// The compiler needs to be instructed that this crate is an allocator in order
78// to realize that when this is linked in another allocator like jemalloc should
79// not be linked in
80#![feature(allocator)]
81#![allocator]
82
83// Allocators are not allowed to depend on the standard library which in turn
84// requires an allocator in order to avoid circular dependencies. This crate,
85// however, can use all of libcore.
b039eaaf
SL
86#![no_std]
87
88// Let's give a unique name to our custom allocator
89#![crate_name = "my_allocator"]
90#![crate_type = "rlib"]
91
92// Our system allocator will use the in-tree libc crate for FFI bindings. Note
93// that currently the external (crates.io) libc cannot be used because it links
94// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why
95// this specifically requires the in-tree version.
96#![feature(libc)]
97extern crate libc;
98
99// Listed below are the five allocation functions currently required by custom
100// allocators. Their signatures and symbol names are not currently typechecked
101// by the compiler, but this is a future extension and are required to match
102// what is found below.
103//
104// Note that the standard `malloc` and `realloc` functions do not provide a way
105// to communicate alignment so this implementation would need to be improved
106// with respect to alignment in that aspect.
107
108#[no_mangle]
109pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 {
110 unsafe { libc::malloc(size as libc::size_t) as *mut u8 }
111}
112
113#[no_mangle]
114pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
115 unsafe { libc::free(ptr as *mut libc::c_void) }
116}
117
118#[no_mangle]
119pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize,
120 _align: usize) -> *mut u8 {
121 unsafe {
122 libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
123 }
124}
125
126#[no_mangle]
127pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize,
128 _size: usize, _align: usize) -> usize {
129 old_size // this api is not supported by libc
130}
131
132#[no_mangle]
133pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
134 size
135}
136
9cc50fc6 137# // only needed to get rustdoc to test this
b039eaaf
SL
138# fn main() {}
139# #[lang = "panic_fmt"] fn panic_fmt() {}
140# #[lang = "eh_personality"] fn eh_personality() {}
141# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
92a42be0
SL
142# #[no_mangle] pub extern fn rust_eh_register_frames () {}
143# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
b039eaaf
SL
144```
145
146After we compile this crate, it can be used as follows:
147
148```rust,ignore
149extern crate my_allocator;
150
151fn main() {
152 let a = Box::new(8); // allocates memory via our custom allocator crate
153 println!("{}", a);
154}
155```
156
157# Custom allocator limitations
158
159There are a few restrictions when working with custom allocators which may cause
160compiler errors:
161
162* Any one artifact may only be linked to at most one allocator. Binaries,
163 dylibs, and staticlibs must link to exactly one allocator, and if none have
164 been explicitly chosen the compiler will choose one. On the other hand rlibs
165 do not need to link to an allocator (but still can).
166
167* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the
168 `liballoc` crate currently) and an `#[allocator]` crate cannot transitively
169 depend on a crate which needs an allocator (e.g. circular dependencies are not
170 allowed). This basically means that allocators must restrict themselves to
171 libcore currently.