目录
一.前言
这篇文章介绍一下Linux系统中如何使用valgrind分析C++程序的内存泄漏。
二.下载安装
下载地址:官网。
或者直接使用命令apt install valgrind
安装。
三.使用valgrind分析内存泄漏
先看代码
//main.cpp
#include<malloc.h>
void Func(void)
{
char* p = (char*)malloc(1024);
}
int main(int argc, char* argv[])
{
Func();
char* p = (char*)malloc(1024);
free(p);
return 0;
}
我们可以看到在Func()
函数中存在内存泄漏的问题。
编译生成一个带调试信息的可执行程序main,命令g++ -g ./main.cpp -o main
。
然后使用valgrind启动main进行分析,命令valgrind ./main
。
可以看到valgrind已经识别到了内存泄漏。
使用--leak-check=full
选项可以查看详细信息,能够看到导致内存泄漏的代码位置,但是需要编译生成可执行程序main的时候带调试信息,命令valgrind --leak-check=full ./main
。
现在有个问题,在上面的示例中是需要main程序退出之后才能得到valgrind的分析结果,但是我们知道,一般常驻在内存中的服务程序是不会随便退出的,那我们能不能在程序退出之前就得到valgrind的分析结果呢,当然是可以的。
修改代码
//main.cpp
#include<malloc.h>
#include<stdio.h>
void Func(void)
{
char* p = (char*)malloc(1024);
}
int main(int argc, char* argv[])
{
Func();
char* p = (char*)malloc(1024);
free(p);
getchar();
return 0;
}
可以看到在代码中使用getchar()
让程序先不要退出,同样使用命令g++ -g ./main.cpp -o main
编译生成main程序,然后使用gdb和valgrind配合的方式来进行调试,因为valgrind内置了gdbserver,所以gdb可以远程调试valgrind启动的程序,具体原理这里不展开了。
启动valgrind的时候可以使用--vgdb=yes
选项来开启gdbserver,命令valgrind --vgdb=yes --leak-check=full ./main
。
可以看到程序正在等待输入,不会退出,也可以直接看到进程号,信息前面的数字就是进程号。
然后我们开启另一个命令窗口,使用gdb调试main程序,命令gdb ./main
。
在gdb中进行远程调试,命令target remote | /usr/bin/vgdb --pid=xxx
。
在gdb中获取valgrind在当前时刻可以生成的分析结果,命令monitor leak_check full reachable any
。
可以看到,这样就可以在程序退出之前就得到valgrind的分析结果了。
需要注意的是在gdb远程连接到进程的时候,进程会阻塞,在得到valgrind的分析结果之后,可以在gdb中使用命令c
让程序继续执行(就是gdb正常调试时的指令)。
现在又有个问题,能不能将valgrind分析结果的输出重定向到文件呢,当然是可以的,命令valgrind --log-file="./valgrind.log" --leak-check=full ./main
。
这样就可以得到valgrind的分析结果文件了。