definitely lost 是必须修复的真正内存泄漏,指无任何指针引用且未 free 的内存块;indirectly lost 是其连带丢失;still reachable 非 bug,因全局/栈上指针仍可达。

直接看“definitely lost”行,它代表真正泄漏、必须修复的内存;其他项多数可忽略或需结合上下文判断。
HEAP SUMMARY 里每行的实际含义
Valgrind 的 HEAP SUMMARY 段落不是统计总览,而是对程序退出时堆状态的快照。它不反映运行中瞬时峰值,只关心“程序结束那一刻”哪些内存块还活着但已不可达。
-
in use at exit:程序退出时仍被持有的堆内存总量(含definitely lost+indirectly lost+still reachable) -
total heap usage:整个生命周期内malloc/free调用次数和字节数,仅作参考,不表示泄漏 -
definitely lost:**关键指标**——内存块无任何指针引用,且未free,100% 是泄漏,必须修复 -
indirectly lost:因父结构体(如链表头)被definitely lost导致的连带丢失,修好父对象后自动消失 -
still reachable:全局/静态指针、栈上局部指针仍指向它,程序结束前没释放,但**不是 bug**(比如日志缓冲区、配置缓存)
为什么 “still reachable” 不等于内存泄漏
它只是说明内存“技术上还能访问”,但不代表你该在退出前手动 free。强行释放可能引发双重释放或破坏单例模式逻辑。
- 常见场景:
static int* g_config = malloc(...)、std::string全局对象内部缓冲区、glibc 的__libc_freeres延迟清理区 - 除非你明确知道该内存本应在退出前释放(比如临时工作区),否则不用管
still reachable - Valgrind 不会报告栈或静态区的越界访问,所以
still reachable数值偏高也可能是正常行为
如何快速定位 definitely lost 的源头
别只盯着 summary,重点看它下面紧跟着的 stack trace —— 那才是修复依据。
- 找到形如
at 0x...: malloc (vg_replace_malloc.c:...)的行,往上翻,找第一个你代码里的函数名(如by 0x401234: parse_json (json.c:42)) - 如果 trace 里全是
???或系统库符号,说明编译时没加-g,或用了-O2+导致行号错乱 - 若看到
operator new但没对应delete,检查 C++ 对象生命周期,尤其是异常路径是否遗漏delete - 多线程程序中,
definitely lost可能来自线程局部存储(TLS)未清理,需检查pthread_key_create+pthread_setspecific配对
容易被忽略的关键点
HEAP SUMMARY 的数字本身没意义,脱离具体 trace 就下结论是最大陷阱。一个 definitely lost: 8 bytes 可能是忘了 free 一个结构体指针,也可能是 malloc(sizeof(int*)) 写成 sizeof(int) 导致后续越界覆盖了元数据——后者 Valgrind 会在 Invalid write 错误里单独报,不在 summary 里体现。











