Claude-skill-registry-data memory-management-optimization
Debug memory leaks, profile memory usage, optimize allocations. Use when heap grows unexpectedly, OOM errors occur, or profiling shows memory bottleneck. Covers C++ (Valgrind, ASAN, RAII), Python (tracemalloc, objgraph), and general patterns.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/memory-management-optimization" ~/.claude/skills/majiayu000-claude-skill-registry-data-memory-management-optimization && rm -rf "$T"
manifest:
data/memory-management-optimization/SKILL.mdsource content
Memory Management Optimization
Persona: Systems programmer who treats memory as a finite resource - every allocation has a cost, every leak is unacceptable.
Process
- Baseline - Measure current memory usage and allocation patterns
- Identify - Find leaks, excessive allocations, or fragmentation
- Analyze - Understand ownership, lifetimes, and allocation sites
- Fix - Apply appropriate solution for the issue type
- Verify - Confirm fix and ensure no regressions
C++ Memory Debugging
Valgrind (Linux)
# Leak detection valgrind --leak-check=full --show-leak-kinds=all ./program # Memory errors valgrind --track-origins=yes ./program # Massif for heap profiling valgrind --tool=massif ./program ms_print massif.out.*
| Valgrind Message | Meaning |
|---|---|
| definitely lost | Leaked, no pointer exists |
| indirectly lost | Leaked via lost pointer |
| possibly lost | Pointer to middle of block |
| still reachable | Not freed at exit (often OK) |
AddressSanitizer (All platforms)
# Compile with ASAN clang++ -fsanitize=address -g program.cpp # Also useful: -fsanitize=leak # Leak detection only -fsanitize=memory # Uninitialized reads (Clang) -fsanitize=undefined # UB detection
RAII Patterns
// BAD: Manual memory management void bad() { int* p = new int[100]; if (error) return; // LEAK delete[] p; } // GOOD: RAII with smart pointers void good() { auto p = std::make_unique<int[]>(100); if (error) return; // Automatic cleanup }
| Ownership | Use |
|---|---|
| Single owner, no sharing |
| Multiple owners |
| Observer, breaks cycles |
| Raw pointer | Non-owning reference only |
Qt-Specific
// Parent-child ownership auto* child = new QWidget(parent); // parent deletes child // deleteLater for event loop safety obj->deleteLater(); // Watch for: // - Deleting QObject during signal handling // - Objects without parents in long-lived containers
Python Memory Debugging
tracemalloc (Built-in)
import tracemalloc tracemalloc.start() # ... code to profile ... snapshot = tracemalloc.take_snapshot() top_stats = snapshot.statistics('lineno') for stat in top_stats[:10]: print(stat)
objgraph (Reference cycles)
import objgraph # Find what's keeping objects alive objgraph.show_backrefs(obj, max_depth=3) # Find objects by type objgraph.by_type('MyClass') # Show growth between snapshots objgraph.show_growth()
Common Python Leaks
| Pattern | Fix |
|---|---|
| Circular references | , break cycle |
| Global caches | Bounded cache, |
| Closures capturing | Copy values, use |
| Event handlers | , weak callbacks |
| Thread-local storage | Clean up on thread exit |
General Optimization Patterns
Object Pooling
// Reuse objects instead of allocate/free class ObjectPool { std::vector<Object*> available; public: Object* acquire() { if (available.empty()) return new Object(); auto* obj = available.back(); available.pop_back(); return obj; } void release(Object* obj) { obj->reset(); available.push_back(obj); } };
Arena Allocators
// Bulk allocate, bulk free class Arena { char* memory; size_t offset = 0; public: void* alloc(size_t size) { void* ptr = memory + offset; offset += size; return ptr; } void reset() { offset = 0; } // Free everything at once };
Avoiding Fragmentation
- Allocate similar-sized objects together
- Use fixed-size blocks where possible
- Consider memory-mapped files for large data
- Pre-allocate containers to final size
Response Format
## Memory Analysis ### Measurements | Metric | Before | After | |--------|--------|-------| | Peak heap | 2.4 GB | 890 MB | | Leak rate | 10 MB/hr | 0 | | Allocs/sec | 50,000 | 8,000 | ### Issues Found 1. **Leak:** `src/cache.cpp:142` - HashMap entries never removed 2. **Fragmentation:** Small allocations in hot loop ### Fixes Applied 1. Added expiry to cache with LRU eviction 2. Replaced per-iteration allocs with object pool ### Verification - Valgrind: 0 leaks - 24hr soak test: stable at 450 MB
Should NOT Attempt
- Premature optimization without profiling data
- Optimizing cold paths
- Changing allocation strategy without benchmarks
- Removing smart pointers for "performance"
Escalation
- Concurrency in allocators →
skill (concurrency section)systematic-debugging - Architecture-level memory design →
agentbackend-architect - Qt/C++ specific issues →
agentcpp-expert - Real-time allocation constraints →
agent (handles embedded/real-time)cpp-expert
When Blocked
If memory debugging stalls:
- Ensure profiling tools are properly installed (Valgrind, ASAN, tracemalloc)
- Verify debug symbols are present (build with -g)
- Try alternative tool (ASAN if Valgrind too slow, tracemalloc for Python)
- For stubborn leaks, add manual logging around suspected allocations
- Report specific tool output and what's been tried
Common Mistakes
| Mistake | Reality |
|---|---|
| "Smart pointers are slow" | Overhead is negligible, safety is worth it |
| "I'll add pooling everywhere" | Only pool when profiling shows benefit |
| "Valgrind is too slow" | Use ASAN for development, Valgrind for releases |
| "Python doesn't leak" | Reference cycles and caches leak constantly |
Related Skills
- systematic-debugging: Debug memory issues methodically
- cpp-expert: C++ memory management, RAII, smart pointers
- qt-qml-expert: Qt object ownership, parent-child memory model