无法定位C程序异常高内存占用问题,valgrind警告不知如何排查
C程序异常大内存占用排查步骤
首先解释你遇到的valgrind警告含义:
69541 Warning: set address range perms: large range [0x76eb040, 0x2cb27240) (undefined)
该警告表示valgrind检测到程序申请了一块约596MB的连续地址区间,远超常规内存分配的大小,是你内存占用过高的直接诱因。
以下是具体定位方法:
- 使用massif工具直接定位内存分配来源
massif是valgrind自带的内存分配分析工具,会记录每块内存的分配调用栈和占用大小,执行命令:valgrind --tool=massif --stacks=yes 你的程序可执行文件路径 [程序运行参数]
程序运行结束后生成massif.out.<进程ID>的结果文件,使用ms_print massif.out.<进程ID>即可查看内存分配统计,排名前列的大内存分配的代码位置、调用栈会直接展示。
注意编译程序时必须添加-g -O0参数,关闭编译优化、保留调试符号,否则无法对应到具体代码行号。 - 给memcheck工具增加参数补全分配栈信息
如果你已经在用memcheck模式运行valgrind,补充以下参数即可输出所有内存分配的调用栈:valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -v 你的程序可执行文件路径 [程序运行参数]
出现上述大内存警告的前后日志中,即可找到对应分配操作的调用栈。 - 用gdb快速断点定位大内存分配
如果valgrind运行太慢,可直接用gdb打断点排查:
启动gdb加载程序后,依次给malloc、calloc、realloc、mmap四个内存分配函数加断点,每次断点触发时打印分配的大小:p size(mmap的话打印第二个参数length),如果分配的数值异常大(接近你观察到的596MB),直接执行bt命令打印调用栈,就能定位到触发大内存分配的代码位置。 - 常见问题排查方向
定位到分配位置后优先检查两类错误:- 内存分配长度计算错误:比如计算数组总大小时溢出、乘法顺序不对导致结果异常大
- 长度参数未初始化:用了未赋值的随机变量作为分配长度参数
确认分配长度正确后,再检查是否存在分配后未释放、全局容器持续写入未清理的问题。
内容的提问来源于stack exchange,提问作者Sergio Giménez
相关产品推荐
相关产品推荐

