Valgrind报告仅malloc结构体的简单代码存在明确丢失内存块,原因是什么?
Valgrind内存泄漏分类判定原理
Valgrind对内存泄漏类别的核心判定依据是:程序完全退出前的扫描阶段,是否存在存活的指针可以直接定位到动态分配内存块的首地址。
两类泄漏的明确定义
- Definitely Lost(明确丢失):没有任何存活的指针指向该内存块的首地址,你无法在程序的任何逻辑中对这块内存执行释放操作,属于完全不可追溯的内存泄漏。
- Still Reachable(仍可到达):存在存活的指针(存储在全局变量、静态变量这类生命周期和整个程序一致的存储区域中)直接或间接指向该内存块的首地址,只要你补充对应的
free逻辑就可以正常释放,只是你没有主动写释放代码而已。
问题原因分析
你的代码里t_env *env是定义在main函数内的局部变量,存储在函数栈帧中。当main执行到return 0时,函数栈帧会被操作系统回收,env这个局部变量本身就被销毁了,它存储的malloc返回的内存地址也就彻底丢失了。Valgrind扫描时只会检查生命周期和程序一致的存储区域(全局数据区、静态存储区),找不到任何指向你分配的t_env结构的指针,因此会判定为明确丢失。
如果你把env修改为全局变量,就会被判定为仍可到达,示例如下:
#include "env.h" // 改为全局变量,生命周期和程序一致 t_env *env; int main(int argc, char **argv, char **envp) { int i; env = malloc(sizeof(t_env)); return (0); }
这种情况下env存储在全局数据区,程序退出时仍然存活,Valgrind可以找到它存储的内存地址,因此会归为仍可到达类别。
补充说明
- 定义在函数内的静态局部变量(加
static修饰)的存储区域是全局数据区,不是栈,生命周期和程序一致,如果这类变量持有未释放的动态内存,也会被判定为仍可到达。 - Valgrind的扫描时机是在所有用户代码执行完毕、进程退出前的清理阶段,此时main函数的栈帧已经销毁,所以main函数内的局部变量不会被纳入扫描范围。
内容的提问来源于stack exchange,提问作者mchun
相关产品推荐
相关产品推荐

