最关键三行是:in use at exit、total heap usage、LEAK SUMMARY;其中in use at exit非0字节即存在未释放或不可达内存,total heap usage中allocs与frees不等提示潜在泄漏风险,LEAK SUMMARY中definitely lost才代表确认的内存泄漏。

HEAP SUMMARY里最关键的三行是什么
直接看 in use at exit、total heap usage 和 LEAK SUMMARY 这三部分,其他全是干扰信息。Valgrind 不会把“没问题”藏在段落里,它用这三行给你下最终判决。
-
in use at exit: 0 bytes in 0 blocks—— 程序退出时堆上没残留内存,这是理想状态;只要不是0 bytes in 0 blocks,就说明有未释放或不可达的内存 -
total heap usage: N allocs, M frees, X bytes allocated—— 关注allocs和frees是否相等;不等 ≠ 一定泄漏(比如全局指针持有),但相等是泄漏为零的必要条件 -
LEAK SUMMARY下的definitely lost才是真泄漏:指那块内存既没被任何指针引用,也没被free,Valgrind 能 100% 确认它丢了
“still reachable”算不算问题
不算泄漏,但可能是设计隐患。still reachable 表示程序结束时仍有指针能访问到那块内存,比如全局变量指向的 malloc 区域、或 main 函数栈上保存的指针。它不会导致资源累积,但掩盖了“该不该在退出前清理”的判断。
- 常见于日志缓冲区、配置缓存、单例对象等长期存活结构
- 如果这类内存随运行时间线性增长(比如每次请求都 new 一个却只靠全局指针 hold),
still reachable数值会变大,这时就得查逻辑了 - Valgrind 默认不报
still reachable,加--show-reachable=yes才显示;日常调试建议先关掉,聚焦真正危险的definitely lost
为什么 HEAP SUMMARY 和 ERROR SUMMARY 对不上
因为它们管的事完全不同:HEAP SUMMARY 只统计“程序退出那一刻”的内存状态,而 ERROR SUMMARY 统计“整个运行过程中”发生的非法操作(越界读写、使用未初始化值、重复 free 等)。
- 一个程序可能
in use at exit: 0 bytes(没泄漏),但中间疯狂Invalid read of size 4—— 这类错误往往导致崩溃或数据错乱,比泄漏更紧急 - 反过来,
definitely lost: 1024 bytes却0 errors from 0 contexts也很常见:纯忘记free,没踩内存也没越界,只是浪费 - 别只盯着
HEAP SUMMARY放心,一定要扫一眼ERROR SUMMARY里的数字;只要不是0 errors from 0 contexts,就必须处理
容易被忽略的细节:block count 和 bytes 的关系
definitely lost: 100 bytes in 2 blocks 这种写法里,“2 blocks”比 “100 bytes” 更值得细看。它意味着泄漏来自两个独立的分配点,而不是同一块内存被多次计数。
- 每个
block对应一次malloc/calloc/realloc调用;Valgrind 会给出每块的调用栈,比如at 0x1092AB: create_string_set_from_file (spellcheck.c:25) - 如果多个 block 指向同一行(比如循环里 malloc 但没配对 free),说明是批量泄漏,修复一处就能清掉整组
- 如果 block 分散在不同文件/函数,得逐个确认释放逻辑——别指望一个
free能覆盖全部


















