In this lesson, you will learn how to instrument your Rust application to track heap object growth over time to detect potential memory leaks.
While Rust’s ownership model prevents most common memory errors, logical leaks—where objects remain referenced in long-lived collections like HashMap or Vec—can still lead to unbounded memory growth. Detecting these requires moving beyond static analysis and into heap telemetry.
Tracking Heap Growth via Custom Allocators
The most robust way to detect leaks is to instrument the global allocator. By wrapping the default allocator, you can intercept every allocation and deallocation event. You can then maintain a thread-safe counter to calculate the "Net Heap Delta."
If the net delta consistently increases while the system is at a steady state (idle), you have confirmed a leak.
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicIsize, Ordering};
struct TrackingAllocator;
static ALLOCATED: AtomicIsize = AtomicIsize::new(0);
unsafe impl GlobalAlloc for TrackingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATED.fetch_add(layout.size() as isize, Ordering::SeqCst);
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
ALLOCATED.fetch_sub(layout.size() as isize, Ordering::SeqCst);
System.dealloc(ptr, layout)
}
}
#[global_allocator]
static A: TrackingAllocator = TrackingAllocator;
Analyzing Growth Patterns
Simply logging the delta is rarely enough. To identify what is leaking, you should correlate heap growth with application phases. Periodically snapshotted metrics—combined with Statistical Sampling Profiling—allow you to see if memory pressure aligns with specific task execution.
If your heap delta trends upward across multiple execution cycles, you are dealing with a classic "leak by accumulation." By tagging these allocations with markers or tracking the growth rate against expected object counts, you can isolate which subsystem is failing to drop its references. This technique complements Analyzing Allocator Pressure, as it provides the granular historical data needed to distinguish between a fragmented heap and a genuine leak.
Key Takeaway: Monitor the net heap delta via a custom global allocator to confirm that object deallocations are keeping pace with allocations during steady-state operations.