想要确认内存泄漏,就得死死盯住RSS(VmRSS)。在业务没有增长等前提下,若观察到它持续缓慢上升,且重启后出现相同的斜率,那很可能就存在问题。可以使用watch或/proc/pid/status进行监控,同时结合pmap -x来比对[anon]/[heap]段Kbytes的增长情况。最后,还能用valgrind(需要优雅退出)或mtrace(仅适用于C语言)来验证是否有definitely lost或未配对的malloc/free操作。

怎么确认某个进程真在泄漏内存
别看VIRT或free里的used,盯死RSS(也就是VmRSS)——它代表进程当前真实占用的物理内存页数。泄漏的表现是:无业务增长、无缓存预热、无连接数上升的前提下,RSS持续缓慢爬升;重启后归零,几小时内又回到相同斜率。
那该怎么验证呢?可以用watch -n 30 'ps -p 每隔30秒抓取一次;或者直接读取/proc/里的VmRSS字段,即执行cat /proc/。然后连续观察2到4小时,只有出现单调递增的趋势,才值得深入研究。
- Ja va/Golang等带GC的语言,
RSS涨不等于泄漏——得排除堆外内存(如ByteBuffer.allocateDirect)、JNI调用、或mmap文件映射未释放 top里按Shift+M排序后看到的RES列,和ps的rss是同一值,可信- 如果
RSS稳定但VmSize(虚拟地址空间)持续增大,可能是mmap未munmap,不是传统“malloc泄漏”
pmap -x 看出哪块内存在偷偷长大
pmap -x 输出里真正要盯的是Kbytes列和Mapping列。泄漏常表现为[anon]段或[heap]段的大小随时间推移明显变大,尤其是多次执行后发现某段地址范围反复膨胀。
操作建议:
先记下初始值:pmap -x ;
过10–15分钟再跑一次,对比Kbytes变化;
若某[anon]段从1280涨到3840,且没有对应业务动作(如加载大文件、建新连接),基本就是泄漏信号。
- 注意
pmap -XX能显示页表级细节,如果看到大量1 page或4KB的[anon]映射,大概率是频繁malloc小块内存却没free pmap本身不报错、不告警,它只反映现状。必须人工比对多个时间点,不能单次快照下结论- 服务类进程(如daemon)需确保
kill -15让其优雅退出,否则pmap看到的只是运行中快照,无法体现释放行为
valgrind --leak-check=full 必须等程序完整退出才出报告
valgrind不是实时监控工具,它是靠插桩拦截所有malloc/free调用,只有程序彻底退出时才汇总并报告“definitely lost”或“possibly lost”。所以对长期运行的服务,得发SIGTERM让它干净收尾,不能kill -9。
关键命令:valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./your_program。
输出里重点看以definitely lost开头的块,后面跟着的堆栈会精确到example.c:42这种行号。
- 编译必须带
-g,否则堆栈里只有地址,没法定位源码 - 动态链接库路径要提前设好:
export LD_LIBRARY_PATH=./lib,不然valgrind可能找不到符号 - 性能开销极大(10–30倍慢),生产环境慎用;测试环境优先选
gcc -O0 -g编译,避免优化导致行号错位
mtrace 更轻量,但只适用于已知源码的C程序
mtrace是glibc自带的轻量方案,不用额外安装,适合快速验证一段C代码是否漏free。但它要求你在源码里手动插入#include 和mtrace()调用,且只能捕获malloc/realloc/free路径。
步骤:
1. 在main()开头加mtrace();
2. 编译加-g;
3. 运行前设export MALLOC_TRACE=/tmp/mtrace.log;
4. 运行程序至结束;
5. 执行mtrace ./your_program /tmp/mtrace.log解析日志。
- 输出里会直接告诉你哪行
malloc没配对free,比如test.c:27 - 不支持C++的
new/delete,也不跟踪mmap/brk等系统调用 - 如果程序有多个退出路径(比如信号处理、异常分支),确保所有路径都走到
exit或return,否则mtrace日志不全
真正难的不是工具怎么用,而是区分“泄漏”和“glibc内存池暂不归还”。RSS高≠泄漏,得结合pmap看[anon]是否持续增长、valgrind是否报definitely lost、以及业务逻辑是否真的该释放——很多所谓“泄漏”,其实是没理解malloc背后那层内存管理器的行为。