Project 9: Memory Allocation Tracer (memleak Clone)

A tool that tracks memory allocations and deallocations, identifying memory leaks by finding allocations that are never freed, along with their stack traces.

Quick Reference

Attribute Value
Primary Language C (libbpf)
Alternative Languages Go (cilium/ebpf), Rust (aya)
Difficulty Level 4: Expert
Time Estimate 2-3 weeks
Knowledge Area Memory Debugging / Leak Detection
Tooling libbpf, uprobes
Prerequisites Projects 1-8 completed, understanding of memory allocation

What You Will Build

A tool that tracks memory allocations and deallocations, identifying memory leaks by finding allocations that are never freed, along with their stack traces.

Why It Matters

Memory tracking requires correlating allocation and deallocation events across time, maintaining state for potentially millions of outstanding allocations. This teaches advanced map usage and performance optimization.

Core Challenges

  • Tracing malloc/free → maps to libc uprobes, USDT probes
  • Tracking outstanding allocations → maps to hash maps keyed by address
  • Handling high allocation rates → maps to sampling, filtering
  • Stack trace for each allocation → maps to bpf_get_stack, storage efficiency

Key Concepts

  • Memory Allocation: “The Linux Programming Interface” Chapter 7 - Kerrisk
  • memleak Tool: BCC memleak
  • USDT Probes: “BPF Performance Tools” Chapter 12 - Brendan Gregg

Real-World Outcome

$ sudo ./memleak -p 1234 --top 10
Tracing memory allocations in PID 1234...

[After 60 seconds]

Top 10 outstanding allocations by total size:

  4096 bytes in 1024 allocations from:
    main+0x45 [/app/myapp]
    create_buffer+0x23 [/app/myapp]
    process_request+0x67 [/app/myapp]
    handle_connection+0x89 [/app/myapp]

  2048 bytes in 512 allocations from:
    json_parse+0x34 [libcjson.so]
    parse_response+0x56 [/app/myapp]
    handle_api+0x78 [/app/myapp]

Outstanding: 1536 allocations, 6144 bytes total
Rate: 234 allocs/sec, 456 frees/sec

Implementation Guide

  1. Reproduce the simplest happy-path scenario.
  2. Build the smallest working version of the core feature.
  3. Add input validation and error handling.
  4. Add instrumentation/logging to confirm behavior.
  5. Refactor into clean modules with tests.

Milestones

  • Milestone 1: Minimal working program that runs end-to-end.
  • Milestone 2: Correct outputs for typical inputs.
  • Milestone 3: Robust handling of edge cases.
  • Milestone 4: Clean structure and documented usage.

Validation Checklist

  • Output matches the real-world outcome example
  • Handles invalid inputs safely
  • Provides clear errors and exit codes
  • Repeatable results across runs

References

  • Main guide: LEARN_BPF_EBPF_LINUX.md
  • “BPF Performance Tools” by Brendan Gregg