2018-05-31 18:23:42 +02:00
|
|
|
|
//! Memory allocation APIs
|
|
|
|
|
|
|
2018-05-31 18:36:51 +02:00
|
|
|
|
#![stable(feature = "alloc_module", since = "1.28.0")]
|
2015-06-09 11:52:41 -07:00
|
|
|
|
|
2018-05-31 18:36:51 +02:00
|
|
|
|
#[stable(feature = "alloc_module", since = "1.28.0")]
|
2018-04-02 10:38:07 +02:00
|
|
|
|
#[doc(inline)]
|
2018-04-03 21:05:10 +02:00
|
|
|
|
pub use core::alloc::*;
|
2024-01-13 20:10:00 +01:00
|
|
|
|
use core::hint;
|
2020-10-06 16:37:23 +02:00
|
|
|
|
use core::ptr::{self, NonNull};
|
2015-02-07 18:49:54 -05:00
|
|
|
|
|
2025-02-07 19:42:33 +00:00
|
|
|
|
unsafe extern "Rust" {
|
2023-01-14 16:33:11 +01:00
|
|
|
|
// These are the magic symbols to call the global allocator. rustc generates
|
2023-12-02 13:52:47 +00:00
|
|
|
|
// them to call the global allocator if there is a `#[global_allocator]` attribute
|
2020-10-09 11:31:54 +02:00
|
|
|
|
// (the code expanding that attribute macro generates those functions), or to call
|
2022-10-28 16:48:00 -07:00
|
|
|
|
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
|
2018-11-12 09:00:39 +01:00
|
|
|
|
// otherwise.
|
2019-07-04 10:05:50 -04:00
|
|
|
|
#[rustc_allocator]
|
2022-11-01 08:45:58 -04:00
|
|
|
|
#[rustc_nounwind]
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2025-07-17 21:47:00 +01:00
|
|
|
|
#[rustc_allocator_zeroed_variant = "__rust_alloc_zeroed"]
|
2018-04-03 17:12:57 +02:00
|
|
|
|
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
2022-08-09 09:56:13 -04:00
|
|
|
|
#[rustc_deallocator]
|
2022-11-01 08:45:58 -04:00
|
|
|
|
#[rustc_nounwind]
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 17:12:57 +02:00
|
|
|
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
2022-08-09 09:56:13 -04:00
|
|
|
|
#[rustc_reallocator]
|
2022-11-01 08:45:58 -04:00
|
|
|
|
#[rustc_nounwind]
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 17:12:57 +02:00
|
|
|
|
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
|
2022-08-09 09:56:13 -04:00
|
|
|
|
#[rustc_allocator_zeroed]
|
2022-11-01 08:45:58 -04:00
|
|
|
|
#[rustc_nounwind]
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 17:12:57 +02:00
|
|
|
|
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
2022-09-10 11:33:44 +00:00
|
|
|
|
|
2025-05-15 16:38:46 -07:00
|
|
|
|
#[rustc_nounwind]
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2025-05-15 16:38:46 -07:00
|
|
|
|
fn __rust_no_alloc_shim_is_unstable_v2();
|
2015-02-07 18:49:54 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-31 18:23:42 +02:00
|
|
|
|
/// The global memory allocator.
|
|
|
|
|
|
///
|
2020-12-04 14:47:15 +01:00
|
|
|
|
/// This type implements the [`Allocator`] trait by forwarding calls
|
2018-05-31 18:23:42 +02:00
|
|
|
|
/// to the allocator registered with the `#[global_allocator]` attribute
|
|
|
|
|
|
/// if there is one, or the `std` crate’s default.
|
2019-02-05 16:56:19 +05:30
|
|
|
|
///
|
|
|
|
|
|
/// Note: while this type is unstable, the functionality it provides can be
|
2020-10-12 13:42:49 -07:00
|
|
|
|
/// accessed through the [free functions in `alloc`](self#functions).
|
2018-05-31 18:36:51 +02:00
|
|
|
|
#[unstable(feature = "allocator_api", issue = "32838")]
|
2017-05-23 14:47:41 +02:00
|
|
|
|
#[derive(Copy, Clone, Default, Debug)]
|
2024-03-05 11:32:03 +01:00
|
|
|
|
// the compiler needs to know when a Box uses the global allocator vs a custom one
|
2024-03-19 09:34:31 -04:00
|
|
|
|
#[lang = "global_alloc_ty"]
|
2018-04-03 14:43:34 +02:00
|
|
|
|
pub struct Global;
|
2017-05-23 14:47:41 +02:00
|
|
|
|
|
2024-07-15 12:26:30 +01:00
|
|
|
|
/// Allocates memory with the global allocator.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// This function forwards calls to the [`GlobalAlloc::alloc`] method
|
|
|
|
|
|
/// of the allocator registered with the `#[global_allocator]` attribute
|
|
|
|
|
|
/// if there is one, or the `std` crate’s default.
|
|
|
|
|
|
///
|
2024-11-24 16:38:29 -08:00
|
|
|
|
/// This function is expected to be deprecated in favor of the `allocate` method
|
2020-12-04 14:47:15 +01:00
|
|
|
|
/// of the [`Global`] type when it and the [`Allocator`] trait become stable.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// # Safety
|
|
|
|
|
|
///
|
|
|
|
|
|
/// See [`GlobalAlloc::alloc`].
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// # Examples
|
|
|
|
|
|
///
|
|
|
|
|
|
/// ```
|
2022-07-12 20:43:04 -04:00
|
|
|
|
/// use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// unsafe {
|
|
|
|
|
|
/// let layout = Layout::new::<u16>();
|
|
|
|
|
|
/// let ptr = alloc(layout);
|
2022-07-12 20:43:04 -04:00
|
|
|
|
/// if ptr.is_null() {
|
|
|
|
|
|
/// handle_alloc_error(layout);
|
|
|
|
|
|
/// }
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// *(ptr as *mut u16) = 42;
|
|
|
|
|
|
/// assert_eq!(*(ptr as *mut u16), 42);
|
|
|
|
|
|
///
|
|
|
|
|
|
/// dealloc(ptr, layout);
|
|
|
|
|
|
/// }
|
|
|
|
|
|
/// ```
|
2018-05-31 19:13:37 +02:00
|
|
|
|
#[stable(feature = "global_alloc", since = "1.28.0")]
|
2021-10-30 22:06:31 -04:00
|
|
|
|
#[must_use = "losing the pointer will leak memory"]
|
2018-05-31 16:10:01 +09:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2018-05-31 16:10:01 +09:00
|
|
|
|
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
|
2022-09-10 11:33:44 +00:00
|
|
|
|
unsafe {
|
|
|
|
|
|
// Make sure we don't accidentally allow omitting the allocator shim in
|
|
|
|
|
|
// stable code until it is actually stabilized.
|
2025-05-15 16:38:46 -07:00
|
|
|
|
__rust_no_alloc_shim_is_unstable_v2();
|
2022-09-10 11:33:44 +00:00
|
|
|
|
|
|
|
|
|
|
__rust_alloc(layout.size(), layout.align())
|
|
|
|
|
|
}
|
2018-05-31 16:10:01 +09:00
|
|
|
|
}
|
2017-05-23 14:47:41 +02:00
|
|
|
|
|
2024-07-15 12:26:30 +01:00
|
|
|
|
/// Deallocates memory with the global allocator.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// This function forwards calls to the [`GlobalAlloc::dealloc`] method
|
|
|
|
|
|
/// of the allocator registered with the `#[global_allocator]` attribute
|
|
|
|
|
|
/// if there is one, or the `std` crate’s default.
|
|
|
|
|
|
///
|
2024-11-24 16:38:29 -08:00
|
|
|
|
/// This function is expected to be deprecated in favor of the `deallocate` method
|
2020-12-04 14:47:15 +01:00
|
|
|
|
/// of the [`Global`] type when it and the [`Allocator`] trait become stable.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// # Safety
|
|
|
|
|
|
///
|
|
|
|
|
|
/// See [`GlobalAlloc::dealloc`].
|
2018-05-31 19:13:37 +02:00
|
|
|
|
#[stable(feature = "global_alloc", since = "1.28.0")]
|
2018-05-31 16:10:01 +09:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2018-05-31 16:10:01 +09:00
|
|
|
|
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
2020-05-28 23:27:00 +02:00
|
|
|
|
unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
|
2018-05-31 16:10:01 +09:00
|
|
|
|
}
|
2017-05-23 14:47:41 +02:00
|
|
|
|
|
2024-07-15 12:26:30 +01:00
|
|
|
|
/// Reallocates memory with the global allocator.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// This function forwards calls to the [`GlobalAlloc::realloc`] method
|
|
|
|
|
|
/// of the allocator registered with the `#[global_allocator]` attribute
|
|
|
|
|
|
/// if there is one, or the `std` crate’s default.
|
|
|
|
|
|
///
|
2024-11-24 16:38:29 -08:00
|
|
|
|
/// This function is expected to be deprecated in favor of the `grow` and `shrink` methods
|
2020-12-04 14:47:15 +01:00
|
|
|
|
/// of the [`Global`] type when it and the [`Allocator`] trait become stable.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// # Safety
|
|
|
|
|
|
///
|
|
|
|
|
|
/// See [`GlobalAlloc::realloc`].
|
2018-05-31 19:13:37 +02:00
|
|
|
|
#[stable(feature = "global_alloc", since = "1.28.0")]
|
2021-10-30 22:06:31 -04:00
|
|
|
|
#[must_use = "losing the pointer will leak memory"]
|
2018-05-31 16:10:01 +09:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2018-05-31 16:10:01 +09:00
|
|
|
|
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
2020-05-28 23:27:00 +02:00
|
|
|
|
unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
|
2018-05-31 16:10:01 +09:00
|
|
|
|
}
|
2017-05-23 14:47:41 +02:00
|
|
|
|
|
2024-07-15 12:26:30 +01:00
|
|
|
|
/// Allocates zero-initialized memory with the global allocator.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
|
|
|
|
|
|
/// of the allocator registered with the `#[global_allocator]` attribute
|
|
|
|
|
|
/// if there is one, or the `std` crate’s default.
|
|
|
|
|
|
///
|
2024-11-24 16:38:29 -08:00
|
|
|
|
/// This function is expected to be deprecated in favor of the `allocate_zeroed` method
|
2020-12-04 14:47:15 +01:00
|
|
|
|
/// of the [`Global`] type when it and the [`Allocator`] trait become stable.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// # Safety
|
|
|
|
|
|
///
|
|
|
|
|
|
/// See [`GlobalAlloc::alloc_zeroed`].
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// # Examples
|
|
|
|
|
|
///
|
|
|
|
|
|
/// ```
|
2024-11-11 16:30:37 -08:00
|
|
|
|
/// use std::alloc::{alloc_zeroed, dealloc, handle_alloc_error, Layout};
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// unsafe {
|
|
|
|
|
|
/// let layout = Layout::new::<u16>();
|
|
|
|
|
|
/// let ptr = alloc_zeroed(layout);
|
2024-11-11 16:30:37 -08:00
|
|
|
|
/// if ptr.is_null() {
|
|
|
|
|
|
/// handle_alloc_error(layout);
|
|
|
|
|
|
/// }
|
2018-08-14 08:37:12 -04:00
|
|
|
|
///
|
|
|
|
|
|
/// assert_eq!(*(ptr as *mut u16), 0);
|
|
|
|
|
|
///
|
|
|
|
|
|
/// dealloc(ptr, layout);
|
|
|
|
|
|
/// }
|
|
|
|
|
|
/// ```
|
2018-05-31 19:13:37 +02:00
|
|
|
|
#[stable(feature = "global_alloc", since = "1.28.0")]
|
2021-10-30 22:06:31 -04:00
|
|
|
|
#[must_use = "losing the pointer will leak memory"]
|
2018-05-31 16:10:01 +09:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2018-05-31 16:10:01 +09:00
|
|
|
|
pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
|
2024-09-17 22:26:21 -04:00
|
|
|
|
unsafe {
|
|
|
|
|
|
// Make sure we don't accidentally allow omitting the allocator shim in
|
|
|
|
|
|
// stable code until it is actually stabilized.
|
2025-05-15 16:38:46 -07:00
|
|
|
|
__rust_no_alloc_shim_is_unstable_v2();
|
2024-09-17 22:26:21 -04:00
|
|
|
|
|
|
|
|
|
|
__rust_alloc_zeroed(layout.size(), layout.align())
|
|
|
|
|
|
}
|
2014-05-11 17:41:15 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-18 07:41:06 +02:00
|
|
|
|
impl Global {
|
|
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-09-24 18:10:56 -04:00
|
|
|
|
fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 07:41:06 +02:00
|
|
|
|
match layout.size() {
|
|
|
|
|
|
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
|
|
|
|
|
|
// SAFETY: `layout` is non-zero in size,
|
|
|
|
|
|
size => unsafe {
|
|
|
|
|
|
let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) };
|
2020-09-24 18:10:56 -04:00
|
|
|
|
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
2020-08-18 07:41:06 +02:00
|
|
|
|
Ok(NonNull::slice_from_raw_parts(ptr, size))
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-04 14:47:15 +01:00
|
|
|
|
// SAFETY: Same as `Allocator::grow`
|
2020-08-18 07:41:06 +02:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-08-18 15:22:10 +02:00
|
|
|
|
unsafe fn grow_impl(
|
2020-09-22 21:04:31 -07:00
|
|
|
|
&self,
|
2020-08-18 07:41:06 +02:00
|
|
|
|
ptr: NonNull<u8>,
|
2020-08-18 22:39:33 +02:00
|
|
|
|
old_layout: Layout,
|
|
|
|
|
|
new_layout: Layout,
|
2020-08-18 07:41:06 +02:00
|
|
|
|
zeroed: bool,
|
2020-09-24 18:10:56 -04:00
|
|
|
|
) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 07:41:06 +02:00
|
|
|
|
debug_assert!(
|
2020-08-18 22:39:33 +02:00
|
|
|
|
new_layout.size() >= old_layout.size(),
|
|
|
|
|
|
"`new_layout.size()` must be greater than or equal to `old_layout.size()`"
|
2020-08-18 07:41:06 +02:00
|
|
|
|
);
|
|
|
|
|
|
|
2020-08-18 22:39:33 +02:00
|
|
|
|
match old_layout.size() {
|
|
|
|
|
|
0 => self.alloc_impl(new_layout, zeroed),
|
2020-08-18 07:41:06 +02:00
|
|
|
|
|
|
|
|
|
|
// SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
|
|
|
|
|
|
// as required by safety conditions. Other conditions must be upheld by the caller
|
2020-08-18 22:39:33 +02:00
|
|
|
|
old_size if old_layout.align() == new_layout.align() => unsafe {
|
|
|
|
|
|
let new_size = new_layout.size();
|
|
|
|
|
|
|
|
|
|
|
|
// `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
|
2024-01-13 20:10:00 +01:00
|
|
|
|
hint::assert_unchecked(new_size >= old_layout.size());
|
2020-08-18 07:41:06 +02:00
|
|
|
|
|
2020-08-18 22:39:33 +02:00
|
|
|
|
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
|
2020-09-24 18:10:56 -04:00
|
|
|
|
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
2020-08-18 07:41:06 +02:00
|
|
|
|
if zeroed {
|
|
|
|
|
|
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
|
|
|
|
|
|
},
|
2020-08-18 22:39:33 +02:00
|
|
|
|
|
|
|
|
|
|
// SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
|
|
|
|
|
|
// both the old and new memory allocation are valid for reads and writes for `old_size`
|
|
|
|
|
|
// bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
|
|
|
|
|
|
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
|
|
|
|
|
|
// for `dealloc` must be upheld by the caller.
|
|
|
|
|
|
old_size => unsafe {
|
|
|
|
|
|
let new_ptr = self.alloc_impl(new_layout, zeroed)?;
|
|
|
|
|
|
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
|
2020-12-04 14:47:15 +01:00
|
|
|
|
self.deallocate(ptr, old_layout);
|
2020-08-18 22:39:33 +02:00
|
|
|
|
Ok(new_ptr)
|
|
|
|
|
|
},
|
2020-08-18 07:41:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-31 18:36:51 +02:00
|
|
|
|
#[unstable(feature = "allocator_api", issue = "32838")]
|
2020-12-04 14:47:15 +01:00
|
|
|
|
unsafe impl Allocator for Global {
|
2018-04-04 19:15:22 +02:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-12-04 14:47:15 +01:00
|
|
|
|
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 07:41:06 +02:00
|
|
|
|
self.alloc_impl(layout, false)
|
2020-07-28 12:41:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-29 11:41:36 +02:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-12-04 14:47:15 +01:00
|
|
|
|
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 07:41:06 +02:00
|
|
|
|
self.alloc_impl(layout, true)
|
2018-04-04 19:15:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-12-04 14:47:15 +01:00
|
|
|
|
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
2020-03-25 21:12:12 +01:00
|
|
|
|
if layout.size() != 0 {
|
2025-02-25 13:02:48 -08:00
|
|
|
|
// SAFETY:
|
|
|
|
|
|
// * We have checked that `layout` is non-zero in size.
|
|
|
|
|
|
// * The caller is obligated to provide a layout that "fits", and in this case,
|
|
|
|
|
|
// "fit" always means a layout that is equal to the original, because our
|
|
|
|
|
|
// `allocate()`, `grow()`, and `shrink()` implementations never returns a larger
|
|
|
|
|
|
// allocation than requested.
|
|
|
|
|
|
// * Other conditions must be upheld by the caller, as per `Allocator::deallocate()`'s
|
|
|
|
|
|
// safety documentation.
|
2020-05-28 23:27:00 +02:00
|
|
|
|
unsafe { dealloc(ptr.as_ptr(), layout) }
|
2020-03-07 12:04:40 +01:00
|
|
|
|
}
|
2018-04-04 19:15:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-03-24 11:45:38 +01:00
|
|
|
|
unsafe fn grow(
|
2020-09-22 21:04:31 -07:00
|
|
|
|
&self,
|
2020-03-25 21:12:12 +01:00
|
|
|
|
ptr: NonNull<u8>,
|
2020-08-18 22:39:33 +02:00
|
|
|
|
old_layout: Layout,
|
|
|
|
|
|
new_layout: Layout,
|
2020-09-24 18:10:56 -04:00
|
|
|
|
) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 15:22:10 +02:00
|
|
|
|
// SAFETY: all conditions must be upheld by the caller
|
2020-08-18 22:39:33 +02:00
|
|
|
|
unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
|
2020-07-28 12:41:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-29 11:41:36 +02:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-07-28 12:41:18 +02:00
|
|
|
|
unsafe fn grow_zeroed(
|
2020-09-22 21:04:31 -07:00
|
|
|
|
&self,
|
2020-07-28 12:41:18 +02:00
|
|
|
|
ptr: NonNull<u8>,
|
2020-08-18 22:39:33 +02:00
|
|
|
|
old_layout: Layout,
|
|
|
|
|
|
new_layout: Layout,
|
2020-09-24 18:10:56 -04:00
|
|
|
|
) -> Result<NonNull<[u8]>, AllocError> {
|
2020-08-18 15:22:10 +02:00
|
|
|
|
// SAFETY: all conditions must be upheld by the caller
|
2020-08-18 22:39:33 +02:00
|
|
|
|
unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
|
2018-04-04 19:15:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2020-03-24 11:45:38 +01:00
|
|
|
|
unsafe fn shrink(
|
2020-09-22 21:04:31 -07:00
|
|
|
|
&self,
|
2020-03-25 21:12:12 +01:00
|
|
|
|
ptr: NonNull<u8>,
|
2020-08-18 22:39:33 +02:00
|
|
|
|
old_layout: Layout,
|
|
|
|
|
|
new_layout: Layout,
|
2020-09-24 18:10:56 -04:00
|
|
|
|
) -> Result<NonNull<[u8]>, AllocError> {
|
2020-03-24 11:45:38 +01:00
|
|
|
|
debug_assert!(
|
2020-08-18 22:39:33 +02:00
|
|
|
|
new_layout.size() <= old_layout.size(),
|
|
|
|
|
|
"`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
|
2020-03-24 11:45:38 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
2020-08-18 22:39:33 +02:00
|
|
|
|
match new_layout.size() {
|
2020-08-17 13:23:38 +02:00
|
|
|
|
// SAFETY: conditions must be upheld by the caller
|
2020-08-18 07:41:06 +02:00
|
|
|
|
0 => unsafe {
|
2020-12-04 14:47:15 +01:00
|
|
|
|
self.deallocate(ptr, old_layout);
|
2020-08-18 22:39:33 +02:00
|
|
|
|
Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
|
2020-08-18 07:41:06 +02:00
|
|
|
|
},
|
2020-07-29 11:41:36 +02:00
|
|
|
|
|
2020-08-18 07:41:06 +02:00
|
|
|
|
// SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
|
2020-08-18 22:39:33 +02:00
|
|
|
|
new_size if old_layout.align() == new_layout.align() => unsafe {
|
|
|
|
|
|
// `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
|
2024-01-13 20:10:00 +01:00
|
|
|
|
hint::assert_unchecked(new_size <= old_layout.size());
|
2020-08-18 07:41:06 +02:00
|
|
|
|
|
2020-08-18 22:39:33 +02:00
|
|
|
|
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
|
2020-09-24 18:10:56 -04:00
|
|
|
|
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
2020-08-18 07:41:06 +02:00
|
|
|
|
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
|
|
|
|
|
|
},
|
2020-08-18 22:39:33 +02:00
|
|
|
|
|
|
|
|
|
|
// SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
|
|
|
|
|
|
// both the old and new memory allocation are valid for reads and writes for `new_size`
|
|
|
|
|
|
// bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
|
|
|
|
|
|
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
|
|
|
|
|
|
// for `dealloc` must be upheld by the caller.
|
|
|
|
|
|
new_size => unsafe {
|
2020-12-04 14:47:15 +01:00
|
|
|
|
let new_ptr = self.allocate(new_layout)?;
|
2020-08-18 22:39:33 +02:00
|
|
|
|
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
|
2020-12-04 14:47:15 +01:00
|
|
|
|
self.deallocate(ptr, old_layout);
|
2020-08-18 22:39:33 +02:00
|
|
|
|
Ok(new_ptr)
|
|
|
|
|
|
},
|
2020-08-18 07:41:06 +02:00
|
|
|
|
}
|
2018-04-04 19:15:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-02 21:22:42 +01:00
|
|
|
|
/// The allocator for `Box`.
|
2025-02-06 12:46:33 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2015-05-09 14:50:28 -05:00
|
|
|
|
#[lang = "exchange_malloc"]
|
2014-05-06 22:03:14 -04:00
|
|
|
|
#[inline]
|
2024-09-11 22:17:03 +02:00
|
|
|
|
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
2015-02-09 10:00:46 +03:00
|
|
|
|
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
2020-05-28 23:27:00 +02:00
|
|
|
|
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
2020-12-04 14:47:15 +01:00
|
|
|
|
match Global.allocate(layout) {
|
2020-08-18 22:39:33 +02:00
|
|
|
|
Ok(ptr) => ptr.as_mut_ptr(),
|
2020-03-24 11:45:38 +01:00
|
|
|
|
Err(_) => handle_alloc_error(layout),
|
2014-05-06 22:03:14 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-22 21:56:09 +00:00
|
|
|
|
// # Allocation error handler
|
|
|
|
|
|
|
2023-04-25 00:08:37 +02:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2025-02-07 19:42:33 +00:00
|
|
|
|
unsafe extern "Rust" {
|
2023-04-25 00:08:37 +02:00
|
|
|
|
// This is the magic symbol to call the global alloc error handler. rustc generates
|
|
|
|
|
|
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
|
|
|
|
|
|
// default implementations below (`__rdl_oom`) otherwise.
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2023-04-25 00:08:37 +02:00
|
|
|
|
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
|
2020-10-09 11:17:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-15 12:26:30 +01:00
|
|
|
|
/// Signals a memory allocation error.
|
2018-05-31 18:23:42 +02:00
|
|
|
|
///
|
2023-08-19 13:16:34 -07:00
|
|
|
|
/// Callers of memory allocation APIs wishing to cease execution
|
2018-05-31 18:23:42 +02:00
|
|
|
|
/// in response to an allocation error are encouraged to call this function,
|
2023-08-19 13:16:34 -07:00
|
|
|
|
/// rather than directly invoking [`panic!`] or similar.
|
2023-04-25 00:08:35 +02:00
|
|
|
|
///
|
2023-08-19 13:16:34 -07:00
|
|
|
|
/// This function is guaranteed to diverge (not return normally with a value), but depending on
|
|
|
|
|
|
/// global configuration, it may either panic (resulting in unwinding or aborting as per
|
|
|
|
|
|
/// configuration for all panics), or abort the process (with no unwinding).
|
|
|
|
|
|
///
|
|
|
|
|
|
/// The default behavior is:
|
|
|
|
|
|
///
|
|
|
|
|
|
/// * If the binary links against `std` (typically the case), then
|
|
|
|
|
|
/// print a message to standard error and abort the process.
|
|
|
|
|
|
/// This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
|
|
|
|
|
|
/// Future versions of Rust may panic by default instead.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// * If the binary does not link against `std` (all of its crates are marked
|
|
|
|
|
|
/// [`#![no_std]`][no_std]), then call [`panic!`] with a message.
|
|
|
|
|
|
/// [The panic handler] applies as to any panic.
|
2023-04-25 00:08:35 +02:00
|
|
|
|
///
|
|
|
|
|
|
/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
|
|
|
|
|
|
/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
|
2023-08-19 13:16:34 -07:00
|
|
|
|
/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute
|
|
|
|
|
|
/// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
|
2018-05-31 19:13:57 +02:00
|
|
|
|
#[stable(feature = "global_alloc", since = "1.28.0")]
|
2022-01-04 00:35:53 +09:00
|
|
|
|
#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
|
2025-02-06 12:46:33 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2020-11-18 18:15:03 +01:00
|
|
|
|
#[cold]
|
2024-08-13 23:54:54 +02:00
|
|
|
|
#[optimize(size)]
|
2021-12-23 22:03:12 +09:00
|
|
|
|
pub const fn handle_alloc_error(layout: Layout) -> ! {
|
|
|
|
|
|
const fn ct_error(_: Layout) -> ! {
|
|
|
|
|
|
panic!("allocation failed");
|
2020-09-07 10:45:20 +02:00
|
|
|
|
}
|
2021-12-23 22:03:12 +09:00
|
|
|
|
|
2023-10-25 19:46:06 -04:00
|
|
|
|
#[inline]
|
2021-12-23 22:03:12 +09:00
|
|
|
|
fn rt_error(layout: Layout) -> ! {
|
2023-04-25 00:08:37 +02:00
|
|
|
|
unsafe {
|
|
|
|
|
|
__rust_alloc_error_handler(layout.size(), layout.align());
|
|
|
|
|
|
}
|
2021-12-23 22:03:12 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-25 19:46:06 -04:00
|
|
|
|
#[cfg(not(feature = "panic_immediate_abort"))]
|
2024-03-19 09:34:31 -04:00
|
|
|
|
{
|
2023-10-25 19:46:06 -04:00
|
|
|
|
core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "panic_immediate_abort")]
|
|
|
|
|
|
ct_error(layout)
|
2020-09-07 10:45:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-06 12:46:33 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2020-09-07 10:45:20 +02:00
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
|
#[allow(unused_attributes)]
|
|
|
|
|
|
#[unstable(feature = "alloc_internals", issue = "none")]
|
2020-10-09 11:39:28 +02:00
|
|
|
|
pub mod __alloc_error_handler {
|
2022-10-14 02:24:58 +01:00
|
|
|
|
// called via generated `__rust_alloc_error_handler` if there is no
|
|
|
|
|
|
// `#[alloc_error_handler]`.
|
2020-09-07 10:45:20 +02:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2022-05-14 02:46:46 +01:00
|
|
|
|
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
|
2025-02-07 19:42:33 +00:00
|
|
|
|
unsafe extern "Rust" {
|
2022-12-22 16:32:08 +01:00
|
|
|
|
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
2023-04-25 00:08:33 +02:00
|
|
|
|
// Its value depends on the -Zoom={panic,abort} compiler option.
|
2025-04-02 21:28:54 +01:00
|
|
|
|
#[rustc_std_internal_symbol]
|
2025-07-03 09:17:48 -07:00
|
|
|
|
fn __rust_alloc_error_handler_should_panic_v2() -> u8;
|
2022-12-22 16:32:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 09:17:48 -07:00
|
|
|
|
if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } {
|
2022-12-22 16:32:08 +01:00
|
|
|
|
panic!("memory allocation of {size} bytes failed")
|
|
|
|
|
|
} else {
|
2023-08-27 20:02:46 +02:00
|
|
|
|
core::panicking::panic_nounwind_fmt(
|
|
|
|
|
|
format_args!("memory allocation of {size} bytes failed"),
|
|
|
|
|
|
/* force_no_backtrace */ false,
|
|
|
|
|
|
)
|
2022-12-22 16:32:08 +01:00
|
|
|
|
}
|
2020-09-07 10:45:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|