valgrind --leak-check=full 主要检测四类堆内存问题:堆内存泄漏、使用已释放内存、越界读写、未初始化内存读取;不检查栈越界、全局变量、除零或空指针解引用。

valgrind --leak-check=full 能查出哪些内存问题
它主要抓四类:堆内存泄漏(malloc/calloc/realloc 后没 free)、使用已释放内存(use-after-free)、越界读写(比如数组下标超了 1 字节)、未初始化内存读取(valgrind 会把堆上新分配的内存标记为“未定义”状态)。注意:它不检查栈内存越界或全局变量问题,也不捕获除零、空指针解引用这类运行时崩溃——那些得靠 gdb 或编译器 -fsanitize=address。
编译时必须加 -g 且避免优化
否则 valgrind 报错位置会跳到汇编行,或者漏掉调用栈。实操建议:
- 用
gcc -g -O0 -o myprog myprog.c编译,-O0是硬性要求,-O1及以上会让部分变量被优化进寄存器,导致“未初始化”误报率飙升 - 如果项目用
make,临时改CFLAGS = -g -O0,别动RELEASE相关宏,否则可能跳过调试断言 -
static函数内联后可能丢失符号,若漏报严重,可加-fno-inline
运行 valgrind 时的关键参数组合
单次基础检查推荐这条命令:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose ./myprog arg1 arg2
各参数作用:
-
--leak-check=full:比默认的summary多显示每块泄漏内存的分配点 -
--show-leak-kinds=all:不放过definitely lost、possibly lost、still reachable三类(尤其别忽略still reachable,常是全局链表头没清) -
--track-origins=yes:定位未初始化内存来源(比如从文件读进缓冲区但忘了memset),代价是慢 2–3 倍,但首次检查值得开 - 如果程序跑太久,加
--tool=memcheck显式指定(默认就是它,但显式写更稳)
看到 “Invalid read/write” 却找不到代码位置?
常见原因是:源码路径编译时没保留,或 valgrind 找不到调试信息。先确认两点:
- 执行
file ./myprog,输出里必须含with debug_info;如果显示stripped,说明符号被删了,重编译 - 检查
valgrind输出末尾是否有???行,比如at 0x401234: ??? (in /path/to/myprog)——这代表符号缺失,不是你代码问题 - 若用 IDE(如 VS Code),别直接点“运行”,要手动在终端跑
valgrind,IDE 的调试器集成通常绕过valgrind或禁用调试信息 - 第三方库(如
libcurl)报错但无源码行?加--suppressions=/usr/lib/valgrind/default.supp屏蔽已知误报,别自己删警告
真正难啃的是跨线程的 use-after-free,valgrind 能报但不保证复现顺序,这种得结合 helgrind 工具单独跑。











