Struct System

pub struct System;

The default memory allocator provided by the operating system.

This is based on malloc on Unix platforms and HeapAlloc on Windows, plus related functions. However, it is not valid to mix use of the backing system allocator with System, as this implementation may include extra work, such as to serve alignment requests greater than the alignment provided directly by the backing system allocator.

This type implements the GlobalAlloc trait. Currently the default global allocator is unspecified. Libraries, however, like cdylibs and staticlibs are guaranteed to use the System by default and as such work as if they had this definition:

use std::alloc::System;

#[global_allocator]
static A: System = System;

fn main() {
    let a = Box::new(4); // Allocates from the system allocator.
    println!("{a}");
}

Note that this does not mean you can deallocate allocations from Global with System (or vice-versa), as the Global allocator is special in the compiler. For more details, see the relevant docs about #[global_allocator].

You can also define your own wrapper around System if you'd like, such as keeping track of the number of all bytes allocated (note that due to optimizations, this may not be accurate):

use std::alloc::{System, GlobalAlloc, Layout};
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};

struct Counter;

static ALLOCATED: AtomicUsize = AtomicUsize::new(0);

unsafe impl GlobalAlloc for Counter {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let ret = unsafe { System.alloc(layout) };
        if !ret.is_null() {
            ALLOCATED.fetch_add(layout.size(), Relaxed);
        }
        ret
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        unsafe { System.dealloc(ptr, layout); }
        ALLOCATED.fetch_sub(layout.size(), Relaxed);
    }
}

#[global_allocator]
static A: Counter = Counter;

fn main() {
    println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed));
}

It can also be used directly to allocate memory independently of whatever global allocator has been selected for a Rust program. For example if a Rust program opts in to using jemalloc as the global allocator, System will still allocate memory using malloc and HeapAlloc.

Implementations

impl System

fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow_impl(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError>

Trait Implementations

impl Allocator for System

fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)
unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow_zeroed(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError>
unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError>

impl AllocatorClone for System

impl AllocatorNightly for System

impl Clone for System

fn clone(&self) -> Self

impl Copy for System

impl Debug for System

fn fmt(&self, f: &mut Formatter<'_>) -> Result

impl Default for System

fn default() -> Self

impl GlobalAllocator for System

impl StaticAllocator for System

impl TrivialClone for System

Auto Trait Implementations

impl Freeze for System

impl RefUnwindSafe for System

impl Send for System

impl Sync for System

impl Unpin for System

impl UnsafeUnpin for System

impl UnwindSafe for System

Blanket Implementations

impl<A> GlobalAlloc for System where A: GlobalAllocator + ?Sized,

unsafe fn alloc(&self, layout: Layout) -> *mut u8
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout)
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8

impl<T> Any for System where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for System where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for System where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

impl<T> CloneToUninit for System where T: Clone,

unsafe fn clone_to_uninit(&self, dest: *mut u8)

impl<T> From<T> for System

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> Printable for System where T: Copy + Debug,

impl<T> SizeHint for System where T: ?Sized,

fn lower_bound(&self) -> usize
fn upper_bound(&self) -> Option<usize>

impl<T> SizedTypeProperties for System

impl<T> ToOwned for System where T: Clone,

type Owned = T;
fn to_owned(&self) -> T
fn clone_into(&self, target: &mut T)

impl<T, U> Into<U> for System where U: From<T>,

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom<U> for System where U: Into<T>,

type Error = never;
fn try_from(value: U) -> Result<T, never>

impl<T, U> TryInto<U> for System where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error;
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>