]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
1 | # `global_allocator` |
2 | ||
3 | The tracking issue for this feature is: [#27389] | |
4 | ||
5 | [#27389]: https://github.com/rust-lang/rust/issues/27389 | |
6 | ||
7 | ------------------------ | |
8 | ||
9 | Rust programs may need to change the allocator that they're running with from | |
10 | time to time. This use case is distinct from an allocator-per-collection (e.g. a | |
11 | `Vec` with a custom allocator) and instead is more related to changing the | |
12 | global default allocator, e.g. what `Vec<T>` uses by default. | |
13 | ||
14 | Currently Rust programs don't have a specified global allocator. The compiler | |
15 | may link to a version of [jemalloc] on some platforms, but this is not | |
16 | guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed | |
17 | to use the "system allocator" which means something like `malloc` on Unixes and | |
18 | `HeapAlloc` on Windows. | |
19 | ||
20 | [jemalloc]: https://github.com/jemalloc/jemalloc | |
21 | ||
22 | The `#[global_allocator]` attribute, however, allows configuring this choice. | |
23 | You can use this to implement a completely custom global allocator to route all | |
24 | default allocation requests to a custom object. Defined in [RFC 1974] usage | |
25 | looks like: | |
26 | ||
27 | [RFC 1974]: https://github.com/rust-lang/rfcs/pull/1974 | |
28 | ||
29 | ```rust | |
30 | #![feature(global_allocator, allocator_api, heap_api)] | |
31 | ||
83c7162d XL |
32 | use std::alloc::{GlobalAlloc, System, Layout, Opaque}; |
33 | use std::ptr::NonNull; | |
041b39d2 XL |
34 | |
35 | struct MyAllocator; | |
36 | ||
83c7162d XL |
37 | unsafe impl GlobalAlloc for MyAllocator { |
38 | unsafe fn alloc(&self, layout: Layout) -> *mut Opaque { | |
041b39d2 XL |
39 | System.alloc(layout) |
40 | } | |
41 | ||
83c7162d | 42 | unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) { |
041b39d2 XL |
43 | System.dealloc(ptr, layout) |
44 | } | |
45 | } | |
46 | ||
47 | #[global_allocator] | |
48 | static GLOBAL: MyAllocator = MyAllocator; | |
49 | ||
50 | fn main() { | |
51 | // This `Vec` will allocate memory through `GLOBAL` above | |
52 | let mut v = Vec::new(); | |
53 | v.push(1); | |
54 | } | |
55 | ``` | |
56 | ||
57 | And that's it! The `#[global_allocator]` attribute is applied to a `static` | |
83c7162d | 58 | which implements the `Alloc` trait in the `std::alloc` module. Note, though, |
041b39d2 XL |
59 | that the implementation is defined for `&MyAllocator`, not just `MyAllocator`. |
60 | You may wish, however, to also provide `Alloc for MyAllocator` for other use | |
61 | cases. | |
62 | ||
63 | A crate can only have one instance of `#[global_allocator]` and this instance | |
64 | may be loaded through a dependency. For example `#[global_allocator]` above | |
65 | could have been placed in one of the dependencies loaded through `extern crate`. | |
66 | ||
67 | Note that `Alloc` itself is an `unsafe` trait, with much documentation on the | |
68 | trait itself about usage and for implementors. Extra care should be taken when | |
69 | implementing a global allocator as well as the allocator may be called from many | |
70 | portions of the standard library, such as the panicking routine. As a result it | |
71 | is highly recommended to not panic during allocation and work in as many | |
72 | situations with as few dependencies as possible as well. |