基于Valgrind Memcheck工具解析四类内存泄漏类型
Valgrind内存泄漏类型全解析:Directly Lost/Indirectly Lost/Still Reachable/Possibly Lost
咱今天就借着你提供的代码实例,把Valgrind里这四种常见的内存泄漏标记给讲透,每个类型都结合代码和检测结果来分析,保证你能get到本质区别。
示例1:Possibly Lost的场景
示例代码
#include<stdio.h> #include <stdlib.h> main() { int *p, i; p = malloc(10*sizeof(int)); for(i = 0;i < 10;i++) p[i] = i; //free(p); printf("Freed\n "); }
Valgrind检测结果
LEAK SUMMARY: ==31770== definitely lost: 0 bytes in 0 blocks ==31770== indirectly lost: 0 bytes in 0 blocks ==31770== possibly lost: 20 bytes in 1 blocks ==31770== still reachable: 0 bytes in 0 blocks ==31770== suppressed: 0 bytes in 0 blocks
解析
这里标记的Possibly lost(可能泄漏),是Valgrind没法100%确认这块内存是否真的无法被程序访问。通常这种情况出现在:指针指向了堆内存块的中间位置(而非分配时的起始地址),或者程序中存在一些模糊的指针引用(比如指针被局部修改后,Valgrind的追踪链断裂)。在这个例子里,虽然p本身还在栈上,但可能因为循环赋值的操作,Valgrind的追踪逻辑产生了不确定性,所以标记为“可能泄漏”——本质上这块内存确实没被释放,但Valgrind没法绝对确定它已经完全不可达。
示例2:Still Reachable vs Definitely Lost的对比
场景1:无printf语句
示例代码
main() { int *p, i; p = malloc(10*sizeof(int)); // printf("freed"); }
Valgrind检测结果
LEAK SUMMARY: ==14950== definitely lost: 0 bytes in 0 blocks ==14950== indirectly lost: 0 bytes in 0 blocks ==14950== possibly lost: 0 bytes in 0 blocks ==14950== still reachable: 40 bytes in 1 blocks ==14950== suppressed: 0 bytes in 0 blocks
场景2:取消注释printf语句
示例代码
main() { int *p, i; p = malloc(10*sizeof(int)); printf("freed"); }
Valgrind检测结果
LEAK SUMMARY: ==15889== definitely lost: 40 bytes in 1 blocks ==15889== indirectly lost: 0 bytes in 0 blocks ==15889== possibly lost: 0 bytes in 0 blocks ==15889== still reachable: 0 bytes in 0 blocks ==15889== suppressed: 0 bytes in 0 blocks
解析
这两个场景的核心区别在于程序结束时,指针p是否还在Valgrind的可达范围内:
- Still reachable(仍可访问):场景1中,因为没有调用
printf,栈帧里的p指针在程序退出前一直保持有效,Valgrind能追踪到这个指针还指向那块malloc的内存。这种情况严格来说不算“泄漏”——因为程序退出后操作系统会自动回收所有内存,但它提醒你:你没有主动释放你分配的内存,这在长期运行的程序(比如服务器)里会导致内存累积。 - Definitely lost(直接泄漏):场景2中,调用
printf后,栈帧被修改(或者编译器优化导致p的地址被覆盖),程序结束时Valgrind已经找不到任何指向这块内存的有效指针了。这是100%的内存泄漏——程序运行期间这块内存再也无法被访问,也没被释放,会一直占用内存直到程序退出。
四种内存泄漏类型的核心定义总结
- Definitely lost(直接泄漏):Valgrind能完全确认,程序中已经没有任何指针指向这块堆内存,且内存从未被释放。这是最严重的泄漏类型,必须修复。
- Indirectly lost(间接泄漏):通常和复杂数据结构(比如链表、结构体)相关。比如你分配了一个链表节点,节点内部又malloc了一块内存,然后你丢失了节点的指针——此时节点内部的内存就是间接泄漏。简单说:你丢了“容器”的指针,导致容器里的内存也没法访问和释放。
- Still reachable(仍可访问):程序退出时,还有有效指针指向这块内存,但你没主动调用
free。短期运行的程序里这个问题不大,但长期运行的服务必须处理,否则内存会持续增长。 - Possibly lost(可能泄漏):Valgrind的追踪逻辑无法100%确认内存是否不可达,比如指针指向了内存块的中间位置,或者存在模糊的引用。这种情况需要你结合代码排查,确认是否真的是泄漏。
内容的提问来源于stack exchange,提问作者himsikha
相关产品推荐
相关产品推荐

