1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Memory allocation APIs
13 //! In a given program, the standard library has one “global” memory allocator
14 //! that is used for example by `Box<T>` and `Vec<T>`.
16 //! Currently the default global allocator is unspecified.
17 //! The compiler may link to a version of [jemalloc] on some platforms,
18 //! but this is not guaranteed.
19 //! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
20 //! to use the [`System`] by default.
22 //! [jemalloc]: https://github.com/jemalloc/jemalloc
23 //! [`System`]: struct.System.html
25 //! # The `#[global_allocator]` attribute
27 //! This attribute allows configuring the choice of global allocator.
28 //! You can use this to implement a completely custom global allocator
29 //! to route all default allocation requests to a custom object.
32 //! use std::alloc::{GlobalAlloc, System, Layout};
34 //! struct MyAllocator;
36 //! unsafe impl GlobalAlloc for MyAllocator {
37 //! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
38 //! System.alloc(layout)
41 //! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
42 //! System.dealloc(ptr, layout)
46 //! #[global_allocator]
47 //! static GLOBAL: MyAllocator = MyAllocator;
50 //! // This `Vec` will allocate memory through `GLOBAL` above
51 //! let mut v = Vec::new();
56 //! The attribute is used on a `static` item whose type implements the
57 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
59 //! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
61 //! ```rust,ignore (demonstrates crates.io usage)
62 //! extern crate jemallocator;
64 //! use jemallocator::Jemalloc;
66 //! #[global_allocator]
67 //! static GLOBAL: Jemalloc = Jemalloc;
72 //! The `#[global_allocator]` can only be used once in a crate
73 //! or its recursive dependencies.
75 #![stable(feature = "alloc_module", since = "1.28.0")]
77 use core::sync::atomic::{AtomicPtr, Ordering};
79 use sys_common::util::dumb_print;
81 #[stable(feature = "alloc_module", since = "1.28.0")]
83 pub use alloc_crate::alloc::*;
85 #[stable(feature = "alloc_system_type", since = "1.28.0")]
87 pub use alloc_system::System;
89 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
91 /// Registers a custom allocation error hook, replacing any that was previously registered.
93 /// The allocation error hook is invoked when an infallible memory allocation fails, before
94 /// the runtime aborts. The default hook prints a message to standard error,
95 /// but this behavior can be customized with the [`set_alloc_error_hook`] and
96 /// [`take_alloc_error_hook`] functions.
98 /// The hook is provided with a `Layout` struct which contains information
99 /// about the allocation that failed.
101 /// The allocation error hook is a global resource.
102 #[unstable(feature = "alloc_error_hook", issue = "51245")]
103 pub fn set_alloc_error_hook(hook: fn(Layout)) {
104 HOOK.store(hook as *mut (), Ordering::SeqCst);
107 /// Unregisters the current allocation error hook, returning it.
109 /// *See also the function [`set_alloc_error_hook`].*
111 /// If no custom hook is registered, the default hook will be returned.
112 #[unstable(feature = "alloc_error_hook", issue = "51245")]
113 pub fn take_alloc_error_hook() -> fn(Layout) {
114 let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
116 default_alloc_error_hook
118 unsafe { mem::transmute(hook) }
122 fn default_alloc_error_hook(layout: Layout) {
123 dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
128 #[alloc_error_handler]
129 #[unstable(feature = "alloc_internals", issue = "0")]
130 pub fn rust_oom(layout: Layout) -> ! {
131 let hook = HOOK.load(Ordering::SeqCst);
132 let hook: fn(Layout) = if hook.is_null() {
133 default_alloc_error_hook
135 unsafe { mem::transmute(hook) }
138 unsafe { ::sys::abort_internal(); }
143 #[allow(unused_attributes)]
144 #[unstable(feature = "alloc_internals", issue = "0")]
145 pub mod __default_lib_allocator {
146 use super::{System, Layout, GlobalAlloc};
147 // for symbol names src/librustc/middle/allocator.rs
148 // for signatures src/librustc_allocator/lib.rs
150 // linkage directives are provided as part of the current compiler allocator
153 #[rustc_std_internal_symbol]
154 pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
155 let layout = Layout::from_size_align_unchecked(size, align);
159 #[rustc_std_internal_symbol]
160 pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
163 System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
166 #[rustc_std_internal_symbol]
167 pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
170 new_size: usize) -> *mut u8 {
171 let old_layout = Layout::from_size_align_unchecked(old_size, align);
172 System.realloc(ptr, old_layout, new_size)
175 #[rustc_std_internal_symbol]
176 pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
177 let layout = Layout::from_size_align_unchecked(size, align);
178 System.alloc_zeroed(layout)