
Linux 内存泄漏排查不能只靠一个工具,得按“用户态程序”和“内核空间”分场景处理,再配合系统级观察和代码级验证。
用户态程序:用 valgrind 快速定位
valgrind 的 Memcheck 是最常用的内存泄漏检测器,适合 C/C++ 程序。它能捕获 malloc/free 不匹配、访问已释放内存等问题。
- 编译时加 -g 保留调试信息,禁用优化(如 -O0),否则行号和调用栈可能不准
- 运行命令示例:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./myapp - 重点关注输出中的 definitely lost(确认泄漏)、indirectly lost(间接泄漏)和 possibly lost(疑似泄漏)
- 若程序运行时间长、内存占用大,可搭配 massif 工具生成堆内存使用曲线:
valgrind --tool=massif --time-unit=B ./myapp,再用ms_print massif.out.xxxx分析峰值与增长点
轻量高效替代:AddressSanitizer(ASan)
相比 valgrind,ASan 运行开销小(约慢 2 倍),集成在 GCC/Clang 中,更适合日常开发和 CI 流程。
- 编译时加入:
gcc -g -fsanitize=address -fno-omit-frame-pointer myapp.c -o myapp - 直接运行即可,一旦发生泄漏或越界,会打印带堆栈的详细错误报告
- 支持内存泄漏检测(需链接
libasan并启用ASAN_OPTIONS=detect_leaks=1) - 注意:ASan 无法检测未初始化读写(那是 UBSan 的范畴),但对泄漏本身足够可靠
系统级线索:从 /proc 和监控工具入手
当 top/ps 看不到明显高内存进程,但 free 显示可用内存持续下降,就要怀疑内核空间泄漏或隐式内存增长。
- 查总体内存状态:
cat /proc/meminfo | grep -E "(MemAvailable|Slab|SReclaimable|PageTables|KernelStack)",重点关注 Slab 和 SReclaimable 是否异常增长 - 盯住 slab 分配器:
slabtop -o(按活跃对象排序),或grep "size-4096" /proc/slabinfo查特定大小缓存项是否持续增加 - 对比用户进程 PSS:
pmap -x <pid></pid>或ps aux --sort=-%mem,排除误判为“无大进程”实则多个小进程累积占满的情况 - 检查内核日志线索:
dmesg -T | tail -50 | grep -i "memory\|oom\|alloc"
内核模块泄漏:kmemleak + trace-cmd 协同分析
内核空间泄漏不经过 glibc,valgrind 完全无效,必须依赖内核自带机制。
- 确认内核已开启 kmemleak(
CONFIG_DEBUG_KMEMLEAK=y),挂载 debugfs:mount -t debugfs nodev /sys/kernel/debug - 启动扫描并查看结果:
echo scan=10 > /sys/kernel/debug/kmemleakcat /sys/kernel/debug/kmemleak - 若发现可疑地址,用
echo dump=0x... > /sys/kernel/debug/kmemleak查看分配上下文 - 进一步精确定位:用
trace-cmd跟踪 kmalloc/kfree 对应 size-4096 的调用:trace-cmd record -e kmem:kmalloc -e kmem:kfree --filter "bytes==4096" -T,再trace-cmd report比对申请与释放是否成对








