Valgrind 的介绍
Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题。在 Linux 可以使用下面的命令安装 Valgrind:
检测内存泄漏
Valgrind 可以用来检测程序在哪个位置发生内存泄漏,例如下面的程序:
编译程序时,需要加上-g
选项:
使用 Valgrind 检测内存使用情况:
先看看输出信息中的HEAP SUMMARY
,它表示程序在堆上分配内存的情况,其中的1 allocs
表示程序分配了 1 次内存,0 frees
表示程序释放了 0 次内存,4 bytes allocated
表示分配了 4 个字节的内存。
另外,Valgrind 也会报告程序是在哪个位置发生内存泄漏。例如,从下面的信息可以看到,程序发生了一次内存泄漏,位置是main.c
文件的第 5 行:
Valgrind 也可以用来检测 C++ 程序的内存泄漏,下面是一个正常的 C++ 程序,没有发生内存泄漏:
使用 Valgrind 分析这段程序:
使用 Valgrind 分析 C++ 程序时,有一些问题需要留意。例如,这个程序并没有发生内存泄漏,但是从HEAP SUMMARY
可以看到,程序分配了 2 次内存,但却只释放了 1 次内存,为什么会这样呢?
实际上这是由于 C++ 在分配内存时,为了提高效率,使用了它自己的内存池。当程序终止时,内存池的内存才会被操作系统回收,所以 Valgrind 会将这部分内存报告为 reachable 的,需要注意,reachable 的内存不代表内存泄漏,例如,从上面的输出中可以看到,有 72704 个字节是 reachable 的,但没有报告内存泄漏。
检测越界访问
C++ 程序经常出现的 Bug 就是数组越界访问,例如下面的程序出现了越界访问:
使用 Valgrind 分析这段程序,Valgrind 会提示越界访问:
Invalid read of size 4
表示越界读取 4 个字节,这个操作出现在main.cpp
文件的第 7 行。另外可以看到,vector
分配了一块 40 字节的内存,程序越界访问紧急着这块内存之后的 4 个字节。
检测未初始化的内存
另一种经常出现的 Bug,就是程序访问了未初始化的内存。例如:
使用 Valgrind 检测这个程序:
输出中提示了main.cpp
文件的第 6 行访问了未初始化的内存。