Movatterモバイル変換


[0]ホーム

URL:


GlobalAlloc

std::alloc

TraitGlobalAlloc 

1.28.0 ·Source
pub unsafe trait GlobalAlloc {    // Required methods    unsafe fnalloc(&self, layout:Layout) ->*mutu8;    unsafe fndealloc(&self, ptr:*mutu8, layout:Layout);    // Provided methods    unsafe fnalloc_zeroed(&self, layout:Layout) ->*mutu8 { ... }    unsafe fnrealloc(        &self,        ptr:*mutu8,        layout:Layout,        new_size:usize,    ) ->*mutu8 { ... }}
Expand description

A memory allocator that can be registered as the standard library’s defaultthrough the#[global_allocator] attribute.

Some of the methods require that a memory block becurrentlyallocated via an allocator. This means that:

  • the starting address for that memory block was previouslyreturned by a previous call to an allocation methodsuch asalloc, and

  • the memory block has not been subsequently deallocated, whereblocks are deallocated either by being passed to a deallocationmethod such asdealloc or by beingpassed to a reallocation method that returns a non-null pointer.

§Example

usestd::alloc::{GlobalAlloc, Layout};usestd::cell::UnsafeCell;usestd::ptr::null_mut;usestd::sync::atomic::{AtomicUsize, Ordering::Relaxed};constARENA_SIZE: usize =128*1024;constMAX_SUPPORTED_ALIGN: usize =4096;#[repr(C, align(4096))]// 4096 == MAX_SUPPORTED_ALIGNstructSimpleAllocator {    arena: UnsafeCell<[u8; ARENA_SIZE]>,    remaining: AtomicUsize,// we allocate from the top, counting down}#[global_allocator]staticALLOCATOR: SimpleAllocator = SimpleAllocator {    arena: UnsafeCell::new([0x55; ARENA_SIZE]),    remaining: AtomicUsize::new(ARENA_SIZE),};unsafe implSyncforSimpleAllocator {}unsafe implGlobalAllocforSimpleAllocator {unsafe fnalloc(&self, layout: Layout) ->*mutu8 {letsize = layout.size();letalign = layout.align();// `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.        // So we can safely use a mask to ensure alignment without worrying about UB.letalign_mask_to_round_down = !(align -1);ifalign > MAX_SUPPORTED_ALIGN {returnnull_mut();        }letmutallocated =0;ifself.remaining            .fetch_update(Relaxed, Relaxed, |mutremaining| {ifsize > remaining {returnNone;                }                remaining -= size;                remaining &= align_mask_to_round_down;                allocated = remaining;Some(remaining)            })            .is_err()        {returnnull_mut();        };unsafe{self.arena.get().cast::<u8>().add(allocated) }    }unsafe fndealloc(&self, _ptr:*mutu8, _layout: Layout) {}}fnmain() {let_s =format!("allocating a string!");letcurrently = ALLOCATOR.remaining.load(Relaxed);println!("allocated so far: {}", ARENA_SIZE - currently);}

§Safety

TheGlobalAlloc trait is anunsafe trait for a number of reasons, andimplementors must ensure that they adhere to these contracts:

  • It’s undefined behavior if global allocators unwind. This restriction maybe lifted in the future, but currently a panic from any of thesefunctions may lead to memory unsafety.

  • Layout queries and calculations in general must be correct. Callers ofthis trait are allowed to rely on the contracts defined on each method,and implementors must ensure such contracts remain true.

  • You must not rely on allocations actually happening, even if there are explicitheap allocations in the source. The optimizer may detect unused allocations that it can eithereliminate entirely or move to the stack and thus never invoke the allocator. Theoptimizer may further assume that allocation is infallible, so code that used to fail dueto allocator failures may now suddenly work because the optimizer worked around theneed for an allocation. More concretely, the following code example is unsound, irrespectiveof whether your custom allocator allows counting how many allocations have happened.

    drop(Box::new(42));letnumber_of_heap_allocs =/* call private allocator API */;unsafe{ std::hint::assert_unchecked(number_of_heap_allocs >0); }

    Note that the optimizations mentioned above are not the onlyoptimization that can be applied. You may generally not rely on heap allocationshappening if they can be removed without changing program behavior.Whether allocations happen or not is not part of the program behavior, even if itcould be detected via an allocator that tracks allocations by printing or otherwisehaving side effects.

§Re-entrance

When implementing a global allocator one has to be careful not to create an infinitely recursiveimplementation by accident, as many constructs in the Rust standard library may allocate intheir implementation. For example, on some platformsstd::sync::Mutex may allocate, so usingit is highly problematic in a global allocator.

Generally speaking for this reason one should stick to library features available throughcore, and avoid usingstd in a global allocator. A few features fromstd areguaranteed to not use#[global_allocator] to allocate:

Required Methods§

1.28.0 ·Source

unsafe fnalloc(&self, layout:Layout) ->*mutu8

Allocates memory as described by the givenlayout.

Returns a pointer to newly-allocated memory,or null to indicate allocation failure.

§Safety

layout must have non-zero size. Attempting to allocate for a zero-sizedlayout willresult in undefined behavior.

(Extension subtraits might provide more specific bounds onbehavior, e.g., guarantee a sentinel address or a null pointerin response to a zero-size allocation request.)

The allocated block of memory may or may not be initialized.

§Errors

Returning a null pointer indicates that either memory is exhaustedorlayout does not meet this allocator’s size or alignment constraints.

Implementations are encouraged to return null on memoryexhaustion rather than aborting, but this is nota strict requirement. (Specifically: it islegal toimplement this trait atop an underlying native allocationlibrary that aborts on memory exhaustion.)

Clients wishing to abort computation in response to anallocation error are encouraged to call thehandle_alloc_error function,rather than directly invokingpanic! or similar.

1.28.0 ·Source

unsafe fndealloc(&self, ptr:*mutu8, layout:Layout)

Deallocates the block of memory at the givenptr pointer with the givenlayout.

§Safety

The caller must ensure:

  • ptr is a block of memory currently allocated via this allocator and,

  • layout is the same layout that was used to allocate that block ofmemory.

Otherwise the behavior is undefined.

Provided Methods§

1.28.0 ·Source

unsafe fnalloc_zeroed(&self, layout:Layout) ->*mutu8

Behaves likealloc, but also ensures that the contentsare set to zero before being returned.

§Safety

The caller has to ensure thatlayout has non-zero size. Likealloczero sizedlayout will result in undefined behavior.However the allocated block of memory is guaranteed to be initialized.

§Errors

Returning a null pointer indicates that either memory is exhaustedorlayout does not meet allocator’s size or alignment constraints,just as inalloc.

Clients wishing to abort computation in response to anallocation error are encouraged to call thehandle_alloc_error function,rather than directly invokingpanic! or similar.

1.28.0 ·Source

unsafe fnrealloc( &self, ptr:*mutu8, layout:Layout, new_size:usize,) ->*mutu8

Shrinks or grows a block of memory to the givennew_size in bytes.The block is described by the givenptr pointer andlayout.

If this returns a non-null pointer, then ownership of the memory blockreferenced byptr has been transferred to this allocator.Any access to the oldptr is Undefined Behavior, even if theallocation remained in-place. The newly returned pointer is the only valid pointerfor accessing this memory now.

The new memory block is allocated withlayout,but with thesize updated tonew_size in bytes.This new layout must be used when deallocating the new memory block withdealloc.The range0..min(layout.size(), new_size) of the new memory block isguaranteed to have the same values as the original block.

If this method returns null, then ownership of the memoryblock has not been transferred to this allocator, and thecontents of the memory block are unaltered.

§Safety

The caller must ensure that:

  • ptr is allocated via this allocator,

  • layout is the same layout that was usedto allocate that block of memory,

  • new_size is greater than zero.

  • new_size, when rounded up to the nearest multiple oflayout.align(),does not overflowisize (i.e., the rounded value must be less than orequal toisize::MAX).

If these are not followed, the behavior is undefined.

(Extension subtraits might provide more specific bounds onbehavior, e.g., guarantee a sentinel address or a null pointerin response to a zero-size allocation request.)

§Errors

Returns null if the new layout does not meet the sizeand alignment constraints of the allocator, or if reallocationotherwise fails.

Implementations are encouraged to return null on memoryexhaustion rather than panicking or aborting, but this is nota strict requirement. (Specifically: it islegal toimplement this trait atop an underlying native allocationlibrary that aborts on memory exhaustion.)

Clients wishing to abort computation in response to areallocation error are encouraged to call thehandle_alloc_error function,rather than directly invokingpanic! or similar.

Implementors§

1.28.0 ·Source§

implGlobalAlloc forSystem


[8]ページ先頭

©2009-2026 Movatter.jp