]> git.lizzy.rs Git - rust.git/blob - src/liballoc/alloc.rs
Rollup merge of #62600 - emmericp:libtest-add-show-output, r=gnzlbg
[rust.git] / src / liballoc / alloc.rs
1 //! Memory allocation APIs
2
3 #![stable(feature = "alloc_module", since = "1.28.0")]
4
5 use core::intrinsics::{min_align_of_val, size_of_val};
6 use core::ptr::{NonNull, Unique};
7 use core::usize;
8
9 #[stable(feature = "alloc_module", since = "1.28.0")]
10 #[doc(inline)]
11 pub use core::alloc::*;
12
13 #[cfg(test)]
14 mod tests;
15
16 extern "Rust" {
17     // These are the magic symbols to call the global allocator.  rustc generates
18     // them from the `#[global_allocator]` attribute if there is one, or uses the
19     // default implementations in libstd (`__rdl_alloc` etc in `src/libstd/alloc.rs`)
20     // otherwise.
21     #[rustc_allocator]
22     #[rustc_allocator_nounwind]
23     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
24     #[rustc_allocator_nounwind]
25     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
26     #[rustc_allocator_nounwind]
27     fn __rust_realloc(ptr: *mut u8,
28                       old_size: usize,
29                       align: usize,
30                       new_size: usize) -> *mut u8;
31     #[rustc_allocator_nounwind]
32     fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
33 }
34
35 /// The global memory allocator.
36 ///
37 /// This type implements the [`Alloc`] trait by forwarding calls
38 /// to the allocator registered with the `#[global_allocator]` attribute
39 /// if there is one, or the `std` crate’s default.
40 ///
41 /// Note: while this type is unstable, the functionality it provides can be
42 /// accessed through the [free functions in `alloc`](index.html#functions).
43 ///
44 /// [`Alloc`]: trait.Alloc.html
45 #[unstable(feature = "allocator_api", issue = "32838")]
46 #[derive(Copy, Clone, Default, Debug)]
47 pub struct Global;
48
49 /// Allocate memory with the global allocator.
50 ///
51 /// This function forwards calls to the [`GlobalAlloc::alloc`] method
52 /// of the allocator registered with the `#[global_allocator]` attribute
53 /// if there is one, or the `std` crate’s default.
54 ///
55 /// This function is expected to be deprecated in favor of the `alloc` method
56 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
57 ///
58 /// # Safety
59 ///
60 /// See [`GlobalAlloc::alloc`].
61 ///
62 /// [`Global`]: struct.Global.html
63 /// [`Alloc`]: trait.Alloc.html
64 /// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use std::alloc::{alloc, dealloc, Layout};
70 ///
71 /// unsafe {
72 ///     let layout = Layout::new::<u16>();
73 ///     let ptr = alloc(layout);
74 ///
75 ///     *(ptr as *mut u16) = 42;
76 ///     assert_eq!(*(ptr as *mut u16), 42);
77 ///
78 ///     dealloc(ptr, layout);
79 /// }
80 /// ```
81 #[stable(feature = "global_alloc", since = "1.28.0")]
82 #[inline]
83 pub unsafe fn alloc(layout: Layout) -> *mut u8 {
84     __rust_alloc(layout.size(), layout.align())
85 }
86
87 /// Deallocate memory with the global allocator.
88 ///
89 /// This function forwards calls to the [`GlobalAlloc::dealloc`] method
90 /// of the allocator registered with the `#[global_allocator]` attribute
91 /// if there is one, or the `std` crate’s default.
92 ///
93 /// This function is expected to be deprecated in favor of the `dealloc` method
94 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
95 ///
96 /// # Safety
97 ///
98 /// See [`GlobalAlloc::dealloc`].
99 ///
100 /// [`Global`]: struct.Global.html
101 /// [`Alloc`]: trait.Alloc.html
102 /// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
103 #[stable(feature = "global_alloc", since = "1.28.0")]
104 #[inline]
105 pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
106     __rust_dealloc(ptr, layout.size(), layout.align())
107 }
108
109 /// Reallocate memory with the global allocator.
110 ///
111 /// This function forwards calls to the [`GlobalAlloc::realloc`] method
112 /// of the allocator registered with the `#[global_allocator]` attribute
113 /// if there is one, or the `std` crate’s default.
114 ///
115 /// This function is expected to be deprecated in favor of the `realloc` method
116 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
117 ///
118 /// # Safety
119 ///
120 /// See [`GlobalAlloc::realloc`].
121 ///
122 /// [`Global`]: struct.Global.html
123 /// [`Alloc`]: trait.Alloc.html
124 /// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
125 #[stable(feature = "global_alloc", since = "1.28.0")]
126 #[inline]
127 pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
128     __rust_realloc(ptr, layout.size(), layout.align(), new_size)
129 }
130
131 /// Allocate zero-initialized memory with the global allocator.
132 ///
133 /// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
134 /// of the allocator registered with the `#[global_allocator]` attribute
135 /// if there is one, or the `std` crate’s default.
136 ///
137 /// This function is expected to be deprecated in favor of the `alloc_zeroed` method
138 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
139 ///
140 /// # Safety
141 ///
142 /// See [`GlobalAlloc::alloc_zeroed`].
143 ///
144 /// [`Global`]: struct.Global.html
145 /// [`Alloc`]: trait.Alloc.html
146 /// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use std::alloc::{alloc_zeroed, dealloc, Layout};
152 ///
153 /// unsafe {
154 ///     let layout = Layout::new::<u16>();
155 ///     let ptr = alloc_zeroed(layout);
156 ///
157 ///     assert_eq!(*(ptr as *mut u16), 0);
158 ///
159 ///     dealloc(ptr, layout);
160 /// }
161 /// ```
162 #[stable(feature = "global_alloc", since = "1.28.0")]
163 #[inline]
164 pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
165     __rust_alloc_zeroed(layout.size(), layout.align())
166 }
167
168 #[unstable(feature = "allocator_api", issue = "32838")]
169 unsafe impl Alloc for Global {
170     #[inline]
171     unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
172         NonNull::new(alloc(layout)).ok_or(AllocErr)
173     }
174
175     #[inline]
176     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
177         dealloc(ptr.as_ptr(), layout)
178     }
179
180     #[inline]
181     unsafe fn realloc(&mut self,
182                       ptr: NonNull<u8>,
183                       layout: Layout,
184                       new_size: usize)
185                       -> Result<NonNull<u8>, AllocErr>
186     {
187         NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
188     }
189
190     #[inline]
191     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
192         NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr)
193     }
194 }
195
196 /// The allocator for unique pointers.
197 // This function must not unwind. If it does, MIR codegen will fail.
198 #[cfg(not(test))]
199 #[lang = "exchange_malloc"]
200 #[inline]
201 unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
202     if size == 0 {
203         align as *mut u8
204     } else {
205         let layout = Layout::from_size_align_unchecked(size, align);
206         let ptr = alloc(layout);
207         if !ptr.is_null() {
208             ptr
209         } else {
210             handle_alloc_error(layout)
211         }
212     }
213 }
214
215 #[cfg_attr(not(test), lang = "box_free")]
216 #[inline]
217 pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
218     let ptr = ptr.as_ptr();
219     let size = size_of_val(&*ptr);
220     let align = min_align_of_val(&*ptr);
221     // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
222     if size != 0 {
223         let layout = Layout::from_size_align_unchecked(size, align);
224         dealloc(ptr as *mut u8, layout);
225     }
226 }
227
228 /// Abort on memory allocation error or failure.
229 ///
230 /// Callers of memory allocation APIs wishing to abort computation
231 /// in response to an allocation error are encouraged to call this function,
232 /// rather than directly invoking `panic!` or similar.
233 ///
234 /// The default behavior of this function is to print a message to standard error
235 /// and abort the process.
236 /// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
237 ///
238 /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
239 /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
240 #[stable(feature = "global_alloc", since = "1.28.0")]
241 #[rustc_allocator_nounwind]
242 pub fn handle_alloc_error(layout: Layout) -> ! {
243     #[allow(improper_ctypes)]
244     extern "Rust" {
245         #[lang = "oom"]
246         fn oom_impl(layout: Layout) -> !;
247     }
248     unsafe { oom_impl(layout) }
249 }