rust-embedded/rust-raspberrypi-OS-tutorials · critical
Allocation error: {:?}
Error message
Allocation error: {:?} What it means
This is the kernel's #[alloc_error_handler]: it panics when a heap allocation via the GlobalAlloc/HeapAllocator fails (e.g. alloc returns null). In this no_std kernel there is no unwinding, so an OOM allocation aborts via panic with the requested Layout printed. It means the kernel heap (a fixed static pool) is exhausted or the requested size is invalid/too large.
Source
Thrown at 20_timer_callbacks/kernel/src/memory/heap_alloc.rs:67
{}",
operation,
size,
size_h,
size_unit,
addr,
addr + size,
backtrace::Backtrace
);
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
use synchronization::interface::Mutex;
#[alloc_error_handler]
fn alloc_error_handler(layout: Layout) -> ! {
panic!("Allocation error: {:?}", layout)
}
/// Return a reference to the kernel's heap allocator.
pub fn kernel_heap_allocator() -> &'static HeapAllocator {
&KERNEL_HEAP_ALLOCATOR
}
impl HeapAllocator {
/// Create an instance.
pub const fn new() -> Self {
Self {
inner: IRQSafeNullLock::new(LinkedListHeap::empty()),
}
}
/// Print the current heap usage.
pub fn print_usage(&self) {
let (used, free) = KERNEL_HEAP_ALLOCATORView on GitHub (pinned to 644474cc09)
Solutions
- Increase the kernel heap size in the heap allocator configuration/pool definition.
- Audit allocations for leaks (especially per-tick/per-interrupt paths that never drop).
- Handle allocation failure at call sites with fallible APIs (try_reserve, checked constructors) instead of infallible Box/Vec.
- Check that the heap is initialized before any allocation happens during boot.
- Reduce allocation size or reuse buffers; the panic prints the Layout — use it to find the oversized request.
Example fix
// before let buf = Vec::with_capacity(user_size); // after let mut buf = Vec::new(); buf.try_reserve_exact(user_size).map_err(|_| "heap exhausted")?;
Defensive patterns
Strategy: validation
Validate before calling
fn can_allocate(heap_free: usize, layout: core::alloc::Layout) -> bool {
layout.size() <= heap_free && layout.align().is_power_of_two()
} Type guard
fn layout_is_reasonable(layout: core::alloc::Layout, max: usize) -> bool {
layout.size() > 0 && layout.size() <= max
} Try / catch
// alloc_error_handler cannot be caught; use fallible APIs:
if let Err(e) = vec.try_reserve(n) {
log::error!("alloc failed: {:?}", e);
return Err(OutOfMemory);
} Prevention
- Size the kernel heap for peak usage with headroom.
- Never allocate in interrupt/exception handlers without bound checks.
- Use try_reserve / checked allocation APIs for untrusted sizes.
- Track and free per-tick allocations; run leak checks in tests.
When it happens
Trigger: Allocating (Box, Vec, BTreeMap, Arc, etc.) after the fixed-size kernel heap is full; requesting a Layout whose size/align exceeds the largest supported or pool size; a leak accumulating until exhaustion; allocating before heap init in early boot.
Common situations: Unbounded Vec growth in an interrupt/exception handler that never frees; a leaked allocation per timer tick in this timer-callback kernel; heap pool configured too small for the workload; allocating a huge buffer from user-controlled size.
Related errors
- Overflow on Address::sub
- Invalid KERNEL_STATE
- transition_to_single_core_main() called while state != Init
- Attempt to enable IRQ {} for device {}, but driver does not
- Error initializing driver: {}: {}
AI-assisted analysis of rust-embedded/rust-raspberrypi-OS-tutorials@644474cc09 (2026-09-06).
Data as JSON: /api/errors/7365a4eb3c167368.
Report an issue: GitHub.