{"record":{"id":"7365a4eb3c167368","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"allocation-error","errorCode":null,"errorMessage":"Allocation error: {:?}","messagePattern":"Allocation error: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"20_timer_callbacks/kernel/src/memory/heap_alloc.rs","lineNumber":67,"sourceCode":"        {}\",\n        operation,\n        size,\n        size_h,\n        size_unit,\n        addr,\n        addr + size,\n        backtrace::Backtrace\n    );\n}\n\n//--------------------------------------------------------------------------------------------------\n// Public Code\n//--------------------------------------------------------------------------------------------------\nuse synchronization::interface::Mutex;\n\n#[alloc_error_handler]\nfn alloc_error_handler(layout: Layout) -> ! {\n    panic!(\"Allocation error: {:?}\", layout)\n}\n\n/// Return a reference to the kernel's heap allocator.\npub fn kernel_heap_allocator() -> &'static HeapAllocator {\n    &KERNEL_HEAP_ALLOCATOR\n}\n\nimpl HeapAllocator {\n    /// Create an instance.\n    pub const fn new() -> Self {\n        Self {\n            inner: IRQSafeNullLock::new(LinkedListHeap::empty()),\n        }\n    }\n\n    /// Print the current heap usage.\n    pub fn print_usage(&self) {\n        let (used, free) = KERNEL_HEAP_ALLOCATOR","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/memory/heap_alloc.rs#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet buf = Vec::with_capacity(user_size);\n// after\nlet mut buf = Vec::new();\nbuf.try_reserve_exact(user_size).map_err(|_| \"heap exhausted\")?;","handlingStrategy":"validation","validationCode":"fn can_allocate(heap_free: usize, layout: core::alloc::Layout) -> bool {\n    layout.size() <= heap_free && layout.align().is_power_of_two()\n}","typeGuard":"fn layout_is_reasonable(layout: core::alloc::Layout, max: usize) -> bool {\n    layout.size() > 0 && layout.size() <= max\n}","tryCatchPattern":"// alloc_error_handler cannot be caught; use fallible APIs:\nif let Err(e) = vec.try_reserve(n) {\n    log::error!(\"alloc failed: {:?}\", e);\n    return Err(OutOfMemory);\n}","preventionTips":["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."],"tags":["rust","kernel","heap","oom","allocation"],"backgroundTag":"out-of-memory","analyzedSha":"644474cc09f755249f9c55d99a5d1e07a2562fc7","analyzedAt":"2026-09-06T09:25:56.584Z","contentChangedAt":"2026-09-06T09:25:56.584Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}