如何定位C/C++服务器进程内存占用与未释放问题(无需Valgrind)
无需Valgrind的C/C++服务器内存泄漏/留存定位方案
1. pmap:快速定位异常内存区域
- 执行
pmap -x <进程PID>,查看进程内存的详细映射 breakdown:- 重点关注
anon类型的匿名内存块(对应堆分配),对比客户端连接前、高峰、断开后的大小变化,如果断开后仍保持高位,说明堆内存未被释放 - 统计不同内存区域的占比,锁定持续增长的内存段类型
- 重点关注
2. GDB内存快照对比:定位残留内存特征
- 客户端连接前拍堆内存快照:
gdb -p <PID> -ex "dump memory pre_conn.bin 0x0 (void*)$sbrk(0)" -ex quit - 所有客户端断开后再拍一次:
gdb -p <PID> -ex "dump memory post_disconn.bin 0x0 (void*)$sbrk(0)" -ex quit - 用
strings post_disconn.bin | grep -v -f <(strings pre_conn.bin)提取新增的字符串,查找模块名、数据结构标识(如业务日志前缀、结构体字段),快速关联到对应功能模块
3. glibc内存统计:直接查看堆分配状态
- 若进程使用glibc的malloc,直接读取
proc接口:cat /proc/<PID>/malloc_info - 分析输出中的
arena(内存池)、chunk(内存块)信息:- 若存在大量未释放的小
chunk,可能是内存碎片;若大arena持续增长,大概率是内存泄漏 - 对比不同阶段的
malloc_info输出,锁定分配异常的内存池
- 若存在大量未释放的小
4. perf:跟踪内存分配热点
- 记录malloc调用事件:
perf record -e malloc:malloc -p <PID> - 客户端断开后停止记录,生成报告:
perf report - 查看报告中的热点函数,不用深入代码就能找到分配次数最多且未释放的模块;也可使用
perf mem record -p <PID>跟踪内存访问,定位高占用区域
5. mtrace:轻量内存泄漏检测
- 设置环境变量并重启进程:
export MALLOC_TRACE=/tmp/mtrace.log ./your_server - 运行后断开所有客户端,执行分析:
mtrace ./your_server /tmp/mtrace.log - 输出会直接显示未释放内存的分配调用栈,快速定位到出问题的功能模块,无需逐行分析业务代码
内容的提问来源于stack exchange,提问作者ravi
相关产品推荐
相关产品推荐

