Introduction
Memory issues — leaks, fragmentation, excessive allocation, and buffer overflows — are among the hardest bugs to diagnose. Specialized memory analysis tools can pinpoint the exact line of code causing the problem. This article covers Valgrind for C/C++ memory errors, heaptrack for Linux heap profiling, memray for Python memory tracking, and general heap profiling techniques.

Valgrind
The gold standard for C/C++ memory error detection:
Basic memory check
valgrind ./myapp
valgrind --leak-check=yes ./myapp
valgrind --tool=memcheck --leak-check=full ./myapp
Detailed output
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./myapp
Suppress known leaks
valgrind --suppressions=suppressions.txt ./myapp
Generate suppression file
valgrind --leak-check=full --gen-suppressions=all ./myapp 2> suppressions.txt
Cache profiling
valgrind --tool=cachegrind ./myapp
Call graph profiling
valgrind --tool=callgrind ./myapp
Massif (heap profiler)
valgrind --tool=massif ./myapp
ms_print massif.out.12345 # View heap profile
Profile specific duration
valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes ./myapp
// Example of errors Valgrind catches
void memory_errors() {
// Buffer overflow — Valgrind catches this
char buf[10];
buf[10] = 'x'; // Error: invalid write
// Use-after-free
char *ptr = malloc(10);
free(ptr);
ptr[0] = 'a'; // Error: invalid read/write
// Memory leak
char *leak = malloc(100); // Never freed
// Valgrind: definitely lost: 100 bytes
// Uninitialized value
int x;
if (x == 5) {} // Error: conditional depends on uninit value
}
Key tools : memcheck for memory errors and leaks, cachegrind for cache profiling, callgrind for call graph analysis, massif for heap profiling.
heaptrack
A modern Linux heap memory profiler with lower overhead than Valgrind:
Installation
sudo apt install heaptrack # Debian/Ubuntu
brew install heaptrack # macOS (partial)
Profile an application
heaptrack ./myapp
heaptrack ./myapp arg1 arg2
Attach to running process
heaptrack -p 12345
Analyze results
heaptrack_print heaptrack.myapp.12345.gz
heaptrack_gui heaptrack.myapp.12345.gz # GUI viewer
Output analysis
heaptrack_print --print-leak-types --print-total heaptrack.myapp.12345.gz
Key features : Lower overhead than Valgrind (suitable for production-like loads), call-stack-based allocation tracking, detailed time-based allocation charts, peak memory analysis, leak detection.
memray
Python memory profiler with high-resolution tracking:
Installation
pip install memray
Profile a script
memray run myapp.py
memray run -o output.bin myapp.py
Profile with live tracking
memray run --live myapp.py
Attach to running process
memray attach --pid 12345 --output output.bin
Generate reports
memray flamegraph output.bin # Interactive flamegraph
memray table output.bin # Text table report
memray tree output.bin # Tree view
memray stats output.bin # Summary statistics
memray summary output.bin # High-level summary
Compare allocations
memray diff before.bin after.bin
Python native support
Programmatic memory tracking
import memray
with memray.Tracker("profile.bin"):
Code to profile
data = [i for i in range(1000000)]
processed = [x * 2 for x in data]
Decorator for function profiling
@memray.tracker("func_profile.bin")
def my_function():
pass
Context manager with specific recording
with memray.Tracker("allocations.bin", native_traces=True):
large_list = [object() for _ in range(500000)]
Key features : Python-native (no C extension needed in many cases), thread-safe, native stack traces, live tracking, multiple report formats including interactive flamegraphs.
General Heap Profiling
jemalloc heap profiling
Enable jemalloc profiling
export MALLOC_CONF="prof:true,prof_active:true,lg_prof_sample:17"
./myapp
Trigger profile dump
kill -SIGUSR2 $PID # Dumps heap profile
jeprof --show_bytes --pdf ./myapp heap.prof > heap.pdf
Compare profiles
jeprof --show_bytes --pdf ./myapp --base=heap1.prof heap2.prof > diff.pdf
GCC address sanitizer
Compile with address sanitizer
gcc -fsanitize=address -g -O1 myapp.c -o myapp
./myapp # Will detect buffer overflows and use-after-free
Leak sanitizer
gcc -fsanitize=leak -g myapp.c -o myapp
Memory Analysis Workflow
1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\. Detect the issue (OOM or high RSS growth)
2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\. Run with memcheck for memory errors
valgrind --leak-check=full ./myapp
3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\. Profile heap with massif or heaptrack
heaptrack ./myapp
4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\. Analyze the profile
heaptrack_print heaptrack.*.gz
5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\. For Python: use memray
memray run myapp.py
memray flamegraph memray-myapp.*.bin
Comparison
| Tool | Language | Overhead | Best For |
|------|----------|----------|----------|
| Valgrind | C/C++ | 10-20x | Memory errors, leaks |
| heaptrack | C/C++/Rust | 2-3x | Heap allocation profiling |
| memray | Python | 1.5-3x | Python memory tracking |
| jemalloc | C/C++ | Low | Production heap profiling |
| ASan | C/C++ | 2x | Buffer overflows, UAF |
Recommendations
-
C/C++ memory errors : Valgrind memcheck is the definitive tool for finding use-after-free, buffer overflows, and uninitialized values.
-
C/C++ heap profiling : heaptrack for lower overhead than Valgrind, suitable for larger applications.
-
Python memory analysis : memray for high-resolution tracking and flamegraph visualization.
-
Production C/C++ : jemalloc profiling for continuous heap monitoring with minimal overhead.
-
Quick memory error detection : GCC/Clang address sanitizer during development.
Start with the lowest-overhead tool for your language. For C/C++, use ASan during development and heaptrack for deeper analysis. For Python, memray is the best all-around choice. Reserve Valgrind for hard-to-find memory errors that simpler tools miss.
Enjoy this article? Share your thoughts, questions, or experiences in the comments below — your insights help other readers too.
Join the discussion ↓