1 //! Memory allocation APIs
3 #![stable(feature = "alloc_module", since = "1.28.0")]
5 use core
::intrinsics
::{self, min_align_of_val, size_of_val}
;
6 use core
::ptr
::{NonNull, Unique}
;
8 #[stable(feature = "alloc_module", since = "1.28.0")]
10 pub use core
::alloc
::*;
16 // These are the magic symbols to call the global allocator. rustc generates
17 // them from the `#[global_allocator]` attribute if there is one, or uses the
18 // default implementations in libstd (`__rdl_alloc` etc in `src/libstd/alloc.rs`)
21 #[rustc_allocator_nounwind]
22 fn __rust_alloc(size
: usize, align
: usize) -> *mut u8;
23 #[rustc_allocator_nounwind]
24 fn __rust_dealloc(ptr
: *mut u8, size
: usize, align
: usize);
25 #[rustc_allocator_nounwind]
26 fn __rust_realloc(ptr
: *mut u8, old_size
: usize, align
: usize, new_size
: usize) -> *mut u8;
27 #[rustc_allocator_nounwind]
28 fn __rust_alloc_zeroed(size
: usize, align
: usize) -> *mut u8;
31 /// The global memory allocator.
33 /// This type implements the [`AllocRef`] trait by forwarding calls
34 /// to the allocator registered with the `#[global_allocator]` attribute
35 /// if there is one, or the `std` crate’s default.
37 /// Note: while this type is unstable, the functionality it provides can be
38 /// accessed through the [free functions in `alloc`](index.html#functions).
40 /// [`AllocRef`]: trait.AllocRef.html
41 #[unstable(feature = "allocator_api", issue = "32838")]
42 #[derive(Copy, Clone, Default, Debug)]
45 /// Allocate memory with the global allocator.
47 /// This function forwards calls to the [`GlobalAlloc::alloc`] method
48 /// of the allocator registered with the `#[global_allocator]` attribute
49 /// if there is one, or the `std` crate’s default.
51 /// This function is expected to be deprecated in favor of the `alloc` method
52 /// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
56 /// See [`GlobalAlloc::alloc`].
58 /// [`Global`]: struct.Global.html
59 /// [`AllocRef`]: trait.AllocRef.html
60 /// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
65 /// use std::alloc::{alloc, dealloc, Layout};
68 /// let layout = Layout::new::<u16>();
69 /// let ptr = alloc(layout);
71 /// *(ptr as *mut u16) = 42;
72 /// assert_eq!(*(ptr as *mut u16), 42);
74 /// dealloc(ptr, layout);
77 #[stable(feature = "global_alloc", since = "1.28.0")]
79 pub unsafe fn alloc(layout
: Layout
) -> *mut u8 {
80 __rust_alloc(layout
.size(), layout
.align())
83 /// Deallocate memory with the global allocator.
85 /// This function forwards calls to the [`GlobalAlloc::dealloc`] method
86 /// of the allocator registered with the `#[global_allocator]` attribute
87 /// if there is one, or the `std` crate’s default.
89 /// This function is expected to be deprecated in favor of the `dealloc` method
90 /// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
94 /// See [`GlobalAlloc::dealloc`].
96 /// [`Global`]: struct.Global.html
97 /// [`AllocRef`]: trait.AllocRef.html
98 /// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
99 #[stable(feature = "global_alloc", since = "1.28.0")]
101 pub unsafe fn dealloc(ptr
: *mut u8, layout
: Layout
) {
102 __rust_dealloc(ptr
, layout
.size(), layout
.align())
105 /// Reallocate memory with the global allocator.
107 /// This function forwards calls to the [`GlobalAlloc::realloc`] method
108 /// of the allocator registered with the `#[global_allocator]` attribute
109 /// if there is one, or the `std` crate’s default.
111 /// This function is expected to be deprecated in favor of the `realloc` method
112 /// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
116 /// See [`GlobalAlloc::realloc`].
118 /// [`Global`]: struct.Global.html
119 /// [`AllocRef`]: trait.AllocRef.html
120 /// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
121 #[stable(feature = "global_alloc", since = "1.28.0")]
123 pub unsafe fn realloc(ptr
: *mut u8, layout
: Layout
, new_size
: usize) -> *mut u8 {
124 __rust_realloc(ptr
, layout
.size(), layout
.align(), new_size
)
127 /// Allocate zero-initialized memory with the global allocator.
129 /// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
130 /// of the allocator registered with the `#[global_allocator]` attribute
131 /// if there is one, or the `std` crate’s default.
133 /// This function is expected to be deprecated in favor of the `alloc_zeroed` method
134 /// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
138 /// See [`GlobalAlloc::alloc_zeroed`].
140 /// [`Global`]: struct.Global.html
141 /// [`AllocRef`]: trait.AllocRef.html
142 /// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
147 /// use std::alloc::{alloc_zeroed, dealloc, Layout};
150 /// let layout = Layout::new::<u16>();
151 /// let ptr = alloc_zeroed(layout);
153 /// assert_eq!(*(ptr as *mut u16), 0);
155 /// dealloc(ptr, layout);
158 #[stable(feature = "global_alloc", since = "1.28.0")]
160 pub unsafe fn alloc_zeroed(layout
: Layout
) -> *mut u8 {
161 __rust_alloc_zeroed(layout
.size(), layout
.align())
164 #[unstable(feature = "allocator_api", issue = "32838")]
165 unsafe impl AllocRef
for Global
{
167 fn alloc(&mut self, layout
: Layout
, init
: AllocInit
) -> Result
<MemoryBlock
, AllocErr
> {
169 let size
= layout
.size();
171 Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }
)
173 let raw_ptr
= match init
{
174 AllocInit
::Uninitialized
=> alloc(layout
),
175 AllocInit
::Zeroed
=> alloc_zeroed(layout
),
177 let ptr
= NonNull
::new(raw_ptr
).ok_or(AllocErr
)?
;
178 Ok(MemoryBlock { ptr, size }
)
184 unsafe fn dealloc(&mut self, ptr
: NonNull
<u8>, layout
: Layout
) {
185 if layout
.size() != 0 {
186 dealloc(ptr
.as_ptr(), layout
)
196 placement
: ReallocPlacement
,
198 ) -> Result
<MemoryBlock
, AllocErr
> {
199 let size
= layout
.size();
202 "`new_size` must be greater than or equal to `memory.size()`"
205 if size
== new_size
{
206 return Ok(MemoryBlock { ptr, size }
);
210 ReallocPlacement
::InPlace
=> Err(AllocErr
),
211 ReallocPlacement
::MayMove
if layout
.size() == 0 => {
212 let new_layout
= Layout
::from_size_align_unchecked(new_size
, layout
.align());
213 self.alloc(new_layout
, init
)
215 ReallocPlacement
::MayMove
=> {
216 // `realloc` probably checks for `new_size > size` or something similar.
217 intrinsics
::assume(new_size
> size
);
218 let ptr
= realloc(ptr
.as_ptr(), layout
, new_size
);
220 MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }
;
221 init
.init_offset(memory
, size
);
233 placement
: ReallocPlacement
,
234 ) -> Result
<MemoryBlock
, AllocErr
> {
235 let size
= layout
.size();
238 "`new_size` must be smaller than or equal to `memory.size()`"
241 if size
== new_size
{
242 return Ok(MemoryBlock { ptr, size }
);
246 ReallocPlacement
::InPlace
=> Err(AllocErr
),
247 ReallocPlacement
::MayMove
if new_size
== 0 => {
248 self.dealloc(ptr
, layout
);
249 Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }
)
251 ReallocPlacement
::MayMove
=> {
252 // `realloc` probably checks for `new_size < size` or something similar.
253 intrinsics
::assume(new_size
< size
);
254 let ptr
= realloc(ptr
.as_ptr(), layout
, new_size
);
255 Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }
)
261 /// The allocator for unique pointers.
262 // This function must not unwind. If it does, MIR codegen will fail.
264 #[lang = "exchange_malloc"]
266 unsafe fn exchange_malloc(size
: usize, align
: usize) -> *mut u8 {
267 let layout
= Layout
::from_size_align_unchecked(size
, align
);
268 match Global
.alloc(layout
, AllocInit
::Uninitialized
) {
269 Ok(memory
) => memory
.ptr
.as_ptr(),
270 Err(_
) => handle_alloc_error(layout
),
274 #[cfg_attr(not(test), lang = "box_free")]
276 // This signature has to be the same as `Box`, otherwise an ICE will happen.
277 // When an additional parameter to `Box` is added (like `A: AllocRef`), this has to be added here as
279 // For example if `Box` is changed to `struct Box<T: ?Sized, A: AllocRef>(Unique<T>, A)`,
280 // this function has to be changed to `fn box_free<T: ?Sized, A: AllocRef>(Unique<T>, A)` as well.
281 pub(crate) unsafe fn box_free
<T
: ?Sized
>(ptr
: Unique
<T
>) {
282 let size
= size_of_val(ptr
.as_ref());
283 let align
= min_align_of_val(ptr
.as_ref());
284 let layout
= Layout
::from_size_align_unchecked(size
, align
);
285 Global
.dealloc(ptr
.cast().into(), layout
)
288 /// Abort on memory allocation error or failure.
290 /// Callers of memory allocation APIs wishing to abort computation
291 /// in response to an allocation error are encouraged to call this function,
292 /// rather than directly invoking `panic!` or similar.
294 /// The default behavior of this function is to print a message to standard error
295 /// and abort the process.
296 /// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
298 /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
299 /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
300 #[stable(feature = "global_alloc", since = "1.28.0")]
301 #[rustc_allocator_nounwind]
302 pub fn handle_alloc_error(layout
: Layout
) -> ! {
305 fn oom_impl(layout
: Layout
) -> !;
307 unsafe { oom_impl(layout) }