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. Libraries, however,
17 //! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by
20 //! [`System`]: struct.System.html
22 //! # The `#[global_allocator]` attribute
24 //! This attribute allows configuring the choice of global allocator.
25 //! You can use this to implement a completely custom global allocator
26 //! to route all default allocation requests to a custom object.
29 //! use std::alloc::{GlobalAlloc, System, Layout};
31 //! struct MyAllocator;
33 //! unsafe impl GlobalAlloc for MyAllocator {
34 //! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
35 //! System.alloc(layout)
38 //! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
39 //! System.dealloc(ptr, layout)
43 //! #[global_allocator]
44 //! static GLOBAL: MyAllocator = MyAllocator;
47 //! // This `Vec` will allocate memory through `GLOBAL` above
48 //! let mut v = Vec::new();
53 //! The attribute is used on a `static` item whose type implements the
54 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
56 //! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
58 //! ```rust,ignore (demonstrates crates.io usage)
59 //! extern crate jemallocator;
61 //! use jemallocator::Jemalloc;
63 //! #[global_allocator]
64 //! static GLOBAL: Jemalloc = Jemalloc;
69 //! The `#[global_allocator]` can only be used once in a crate
70 //! or its recursive dependencies.
72 #![stable(feature = "alloc_module", since = "1.28.0")]
74 use core::sync::atomic::{AtomicPtr, Ordering};
76 use core::ptr::NonNull;
77 use sys_common::util::dumb_print;
79 #[stable(feature = "alloc_module", since = "1.28.0")]
81 pub use alloc_crate::alloc::*;
83 /// The default memory allocator provided by the operating system.
85 /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
86 /// plus related functions.
88 /// This type implements the `GlobalAlloc` trait and Rust programs by deafult
89 /// work as if they had this definition:
92 /// use std::alloc::System;
94 /// #[global_allocator]
95 /// static A: System = System;
98 /// let a = Box::new(4); // Allocates from the system allocator.
99 /// println!("{}", a);
103 /// You can also define your own wrapper around `System` if you'd like, such as
104 /// keeping track of the number of all bytes allocated:
107 /// use std::alloc::{System, GlobalAlloc, Layout};
108 /// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
112 /// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT;
114 /// unsafe impl GlobalAlloc for Counter {
115 /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
116 /// let ret = System.alloc(layout);
117 /// if !ret.is_null() {
118 /// ALLOCATED.fetch_add(layout.size(), SeqCst);
123 /// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
124 /// System.dealloc(ptr, layout);
125 /// ALLOCATED.fetch_sub(layout.size(), SeqCst);
129 /// #[global_allocator]
130 /// static A: Counter = Counter;
133 /// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
137 /// It can also be used directly to allocate memory independently of whatever
138 /// global allocator has been selected for a Rust program. For example if a Rust
139 /// program opts in to using jemalloc as the global allocator, `System` will
140 /// still allocate memory using `malloc` and `HeapAlloc`.
141 #[stable(feature = "alloc_system_type", since = "1.28.0")]
142 #[derive(Debug, Copy, Clone)]
145 #[unstable(feature = "allocator_api", issue = "32838")]
146 unsafe impl Alloc for System {
148 unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
149 NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
153 unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
154 NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
158 unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
159 GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
163 unsafe fn realloc(&mut self,
166 new_size: usize) -> Result<NonNull<u8>, AllocErr> {
167 NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
171 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
173 /// Registers a custom allocation error hook, replacing any that was previously registered.
175 /// The allocation error hook is invoked when an infallible memory allocation fails, before
176 /// the runtime aborts. The default hook prints a message to standard error,
177 /// but this behavior can be customized with the [`set_alloc_error_hook`] and
178 /// [`take_alloc_error_hook`] functions.
180 /// The hook is provided with a `Layout` struct which contains information
181 /// about the allocation that failed.
183 /// The allocation error hook is a global resource.
184 #[unstable(feature = "alloc_error_hook", issue = "51245")]
185 pub fn set_alloc_error_hook(hook: fn(Layout)) {
186 HOOK.store(hook as *mut (), Ordering::SeqCst);
189 /// Unregisters the current allocation error hook, returning it.
191 /// *See also the function [`set_alloc_error_hook`].*
193 /// If no custom hook is registered, the default hook will be returned.
194 #[unstable(feature = "alloc_error_hook", issue = "51245")]
195 pub fn take_alloc_error_hook() -> fn(Layout) {
196 let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
198 default_alloc_error_hook
200 unsafe { mem::transmute(hook) }
204 fn default_alloc_error_hook(layout: Layout) {
205 dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
210 #[alloc_error_handler]
211 #[unstable(feature = "alloc_internals", issue = "0")]
212 pub fn rust_oom(layout: Layout) -> ! {
213 let hook = HOOK.load(Ordering::SeqCst);
214 let hook: fn(Layout) = if hook.is_null() {
215 default_alloc_error_hook
217 unsafe { mem::transmute(hook) }
220 unsafe { ::sys::abort_internal(); }
225 #[allow(unused_attributes)]
226 #[unstable(feature = "alloc_internals", issue = "0")]
227 pub mod __default_lib_allocator {
228 use super::{System, Layout, GlobalAlloc};
229 // for symbol names src/librustc/middle/allocator.rs
230 // for signatures src/librustc_allocator/lib.rs
232 // linkage directives are provided as part of the current compiler allocator
235 #[rustc_std_internal_symbol]
236 pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
237 let layout = Layout::from_size_align_unchecked(size, align);
241 #[rustc_std_internal_symbol]
242 pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
245 System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
248 #[rustc_std_internal_symbol]
249 pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
252 new_size: usize) -> *mut u8 {
253 let old_layout = Layout::from_size_align_unchecked(old_size, align);
254 System.realloc(ptr, old_layout, new_size)
257 #[rustc_std_internal_symbol]
258 pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
259 let layout = Layout::from_size_align_unchecked(size, align);
260 System.alloc_zeroed(layout)