Skip to main content

DebugCheckingAllocator

Struct DebugCheckingAllocator 

Source
pub struct DebugCheckingAllocator<A>
where A: BStackAllocator<Error = Error>,
{ /* private fields */ }
Expand description

Debug-only allocator wrapper that validates allocations and deallocations.

Wraps any allocator whose Allocated type is BStackOwnedSlice and whose Error is io::Error. Maintains in-memory sets of allocated and freed regions and validates every operation against them.

§Panics

Panics if:

  • A newly allocated region overlaps with an existing allocated region
  • A reallocated region overlaps with an existing allocated region
  • A region being freed overlaps with a previously freed region

These panics indicate bugs in the underlying allocator implementation or a double free in the calling code.

§Thread Safety

The internal tracking sets are protected by a Mutex for internal bookkeeping, but allocation operations and tracking updates must not be assumed to be an atomic, cross-thread synchronization boundary. Concurrent use of this debug wrapper is therefore not supported unless the caller provides external synchronization.

Implementations§

Source§

impl<A> DebugCheckingAllocator<A>
where A: BStackAllocator<Error = Error>,

Source

pub fn new(inner: A) -> Self

Create a new DebugCheckingAllocator wrapping inner.

The allocator starts with empty tracking sets. If you’re reopening a file from a previous session and want to pre-populate those sets, use Self::with_state instead.

Source

pub fn with_state( inner: A, allocated: impl IntoIterator<Item = Range<u64>>, freed: impl IntoIterator<Item = Range<u64>>, ) -> Self

Create a new DebugCheckingAllocator wrapping inner, with pre-populated tracking sets.

Use this when reopening a file from a previous session and you have metadata to reconstruct which regions were allocated or freed.

§Panics

Panics if the initial state is inconsistent:

  • Any two ranges within allocated overlap
  • Any two ranges within freed overlap
  • Any range in allocated overlaps with any range in freed
Source

pub fn inner(&self) -> &A

Return a reference to the inner allocator.

Source

pub fn into_inner(self) -> A

Consume this allocator and return the inner allocator.

Trait Implementations§

Source§

impl<A> BStackAllocator for DebugCheckingAllocator<A>
where for<'b> A: 'static + BStackAllocator<Error = Error> + BStackAllocator<Allocated<'b> = BStackOwnedSlice<'b, A>>,

Source§

type Error = Error

The error type returned by alloc, realloc, dealloc, alloc_bulk, and dealloc_bulk. Read more
Source§

type Allocated<'a> = BStackOwnedSlice<'a, DebugCheckingAllocator<A>> where Self: 'a

The handle type returned by alloc and realloc, and accepted by realloc and dealloc. Read more
Source§

fn stack(&self) -> &BStack

Return a shared reference to the underlying BStack. Read more
Source§

fn into_stack(self) -> BStack

Consume the allocator and return the underlying BStack. Read more
Source§

fn alloc(&self, len: u64) -> Result<Self::Allocated<'_>>

Allocate len zero-initialised bytes. Read more
Source§

fn realloc<'a>( &'a self, handle: BStackOwnedSlice<'a, Self>, new_len: u64, ) -> Result<BStackOwnedSlice<'a, Self>, BStackAllocError<'a, Self>>

Resize the region described by handle to new_len bytes. Read more
Source§

fn dealloc<'a>( &'a self, handle: BStackOwnedSlice<'a, Self>, ) -> Result<(), BStackAllocError<'a, Self>>

Release the region described by handle. Read more
Source§

fn len(&self) -> Result<u64>

Return the current logical length of the backing stack payload. Read more
Source§

fn is_empty(&self) -> Result<bool>

Return true if the backing stack is empty. Read more
Source§

impl<A> BStackBulkAllocator for DebugCheckingAllocator<A>
where for<'b> A: 'static + BStackBulkAllocator<Error = Error> + BStackAllocator<Allocated<'b> = BStackOwnedSlice<'b, A>>,

Source§

fn alloc_bulk( &self, lengths: impl AsRef<[u64]>, ) -> Result<Vec<Self::Allocated<'_>>>

Allocate slices with the given lengths in a single atomic operation. Read more
Source§

fn dealloc_bulk<'a>( &'a self, handles: impl IntoIterator<Item = BStackOwnedSlice<'a, Self>>, ) -> Result<(), BStackBulkAllocError<'a, Self>>

Deallocate multiple handles in a single atomic operation. Read more
Source§

impl<A> BStackInPlaceResizeAllocator for DebugCheckingAllocator<A>
where for<'b> A: 'static + BStackInPlaceResizeAllocator<Error = Error> + BStackAllocator<Allocated<'b> = BStackOwnedSlice<'b, A>>,

Forwards to the inner allocator’s front/back in-place resize, with the same overlap checking as realloc.

Only available when the wrapped allocator implements BStackInPlaceResizeAllocator itself, for the same reason as BStackUninitAllocator above: the wrapper never fabricates a structural guarantee the inner allocator does not make.

A nonzero prepend moves the region’s start, so unlike realloc the tracked region cannot simply be resized in place: the old (start, len) is retired into the freed set and (start - prepend, len + prepend + append) is recorded as newly allocated, exactly as a relocating realloc would be tracked. A debug assertion checks the trait’s exact-position guarantee on every success. An Unsupported failure is a clean pre-mutation rejection — the inner handle comes back untouched and tracking is left exactly as it was.

Source§

fn realloc_inplace<'a>( &'a self, handle: BStackOwnedSlice<'a, Self>, prepend: i64, append: i64, ) -> Result<BStackOwnedSlice<'a, Self>, BStackAllocError<'a, Self>>

Resize handle in place by prepend bytes at the front and append bytes at the back in one call. Read more
Source§

impl<A> BStackUninitAllocator for DebugCheckingAllocator<A>
where for<'b> A: 'static + BStackUninitAllocator<Error = Error> + BStackAllocator<Allocated<'b> = BStackOwnedSlice<'b, A>>,

Forwards to the inner allocator’s uninitialised path, with the same bookkeeping as alloc / realloc.

Only available when the wrapped allocator implements BStackUninitAllocator itself — the wrapper never fabricates the trait for an allocator that has no cheaper uninitialised path, so DebugCheckingAllocator<A>: BStackUninitAllocator is exactly as truthful a signal as A: BStackUninitAllocator.

The overlap, double-free and partial-free checks are unaffected: they are driven by allocation coordinates, which the uninitialised path produces exactly as the initialised one does. The wrapper does not (and cannot) verify region contents, so it makes no assertion about whether returned bytes are zero.

Source§

fn alloc_uninit(&self, len: u64) -> Result<Self::Allocated<'_>>

Allocate len bytes without zero-initialising them. Read more
Source§

fn realloc_uninit<'a>( &'a self, handle: BStackOwnedSlice<'a, Self>, new_len: u64, ) -> Result<BStackOwnedSlice<'a, Self>, BStackAllocError<'a, Self>>

Resize the region described by handle to new_len bytes without zero-initialising any newly added bytes. Read more
Source§

impl<A> Debug for DebugCheckingAllocator<A>
where A: BStackAllocator<Error = Error> + Debug,

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<A> BStackOwnedSliceAllocator for A
where A: BStackAllocator<Error = Error, Allocated<'a> = BStackOwnedSlice<'a, A>> + for<'a> BStackAllocator + 'static,

Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

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

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.