目录
一、概述
Valgrind是一套开放源代码(GPL V2)的仿真调试工具集合,由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件(plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Valgrind 是一个强大的内存调试和性能分析工具,广泛用于 Linux 系统上的程序开发和测试。它可以帮助开发者检测内存泄漏、数组越界、未初始化变量等问题,并提供详细的报告。Valgrind 支持多种编程语言,尤其是 C 和 C++。
Valgrind可以帮助开发者检测和修复程序中的内存问题和性能瓶颈。通过合理使用 Valgrind 的各种工具和选项,可以显著提高程序的质量和性能。
二、 主要功能
主要功能包括:
1. 内存泄漏检测:检测程序中未释放的内存分配。
2. 数组越界检测:检测数组访问越界的情况。
3. 未初始化变量检测:检测使用未初始化的变量。
4. 多线程错误检测:检测线程同步问题,如数据竞争。
5. 性能分析:提供详细的性能分析报告,帮助优化程序。
三、 安装 Valgrind
(一)在 Ubuntu 上安装 Valgrind
使用如下命令:
sudo apt update
sudo apt install valgrind
实际操作如下:
root@quinn-ThinkPad-T430s:/studyLinux/performance# valgrind -h
找不到命令 “valgrind”,但可以通过以下软件包安装它:
snap install valgrind # version 3.22.0, or
apt install valgrind # version 1:3.18.1-1ubuntu2
输入 “snap info valgrind” 以查看更多版本。
root@quinn-ThinkPad-T430s:/studyLinux/performance# sudo apt update
获取:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
命中:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy InRelease
获取:3 http://security.ubuntu.com/ubuntu jammy-security/main amd64 DEP-11 Metadata [43.2 kB]
获取:4 http://security.ubuntu.com/ubuntu jammy-security/restricted amd64 DEP-11 Metadata [208 B]
获取:5 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 DEP-11 Metadata [125 kB]
获取:6 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 DEP-11 Metadata [208 B]
获取:7 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates InRelease [128 kB]
获取:8 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 DEP-11 Metadata [103 kB]
获取:9 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/restricted amd64 DEP-11 Metadata [212 B]
获取:10 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/universe amd64 DEP-11 Metadata [356 kB]
获取:11 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/multiverse amd64 DEP-11 Metadata [940 B]
获取:12 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports InRelease [127 kB]
获取:13 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports/main amd64 DEP-11 Metadata [5,344 B]
获取:14 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports/restricted amd64 DEP-11 Metadata [212 B]
获取:15 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports/universe amd64 DEP-11 Metadata [23.1 kB]
获取:16 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports/multiverse amd64 DEP-11 Metadata [212 B]
已下载 1,042 kB,耗时 23秒 (45.5 kB/s)
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
有 197 个软件包可以升级。请执行 ‘apt list --upgradable’ 来查看它们。
root@quinn-ThinkPad-T430s:/studyLinux/performance#
root@quinn-ThinkPad-T430s:/studyLinux/performance# sudo apt install valgrind
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
将会同时安装下列软件:
libc6-i386
建议安装:
valgrind-dbg valgrind-mpi kcachegrind alleyoop valkyrie
下列【新】软件包将被安装:
libc6-i386 valgrind
升级了 0 个软件包,新安装了 2 个软件包,要卸载 0 个软件包,有 197 个软件包未被升级。
需要下载 16.9 MB 的归档。
解压缩后会消耗 91.8 MB 的额外空间。
您希望继续执行吗? [Y/n] y
获取:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 libc6-i386 amd64 2.35-0ubuntu3.8 [2,838 kB]
获取:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/main amd64 valgrind amd64 1:3.18.1-1ubuntu2 [14.1 MB]
已下载 16.9 MB,耗时 10秒 (1,639 kB/s)
正在选中未选择的软件包 libc6-i386。
(正在读取数据库 ... 系统当前共安装有 216991 个文件和目录。)
准备解压 .../libc6-i386_2.35-0ubuntu3.8_amd64.deb ...
正在解压 libc6-i386 (2.35-0ubuntu3.8) ...
正在选中未选择的软件包 valgrind。
准备解压 .../valgrind_1%3a3.18.1-1ubuntu2_amd64.deb ...
正在解压 valgrind (1:3.18.1-1ubuntu2) ...
正在设置 libc6-i386 (2.35-0ubuntu3.8) ...
正在设置 valgrind (1:3.18.1-1ubuntu2) ...
正在处理用于 man-db (2.10.2-1) 的触发器 ...
正在处理用于 libc-bin (2.35-0ubuntu3.8) 的触发器 ...
root@quinn-ThinkPad-T430s:/studyLinux/performance# valgrind -h
usage: valgrind [options] prog-and-args
tool-selection option, with default in [ ]:
--tool=<name> use the Valgrind tool named <name> [memcheck]
basic user options for all Valgrind tools, with defaults in [ ]:
(二)在 CentOS 上安装 Valgrind
使用如下命令:
sudo yum install valgrind
四、 使用 Valgrind
(一) 基本用法
Valgrind 的基本用法是:
valgrind [valgrind-options] ./your-program [program-options]
其中,[valgrind-options]表示Valgrind的选项。
(二) 选项
1. 常用选项
包括:
- --tool=tool_name:指定要使用的Valgrind工具,如Memcheck、Callgrind等。
- --leak-check=full:在程序退出时检查内存泄漏,并显示所有的内存泄漏信息。
- --track-origins=yes:跟踪未初始化变量的来源。
- --log-file=<文件>:将Valgrind输出的信息保存至文件中。
2. 内存泄漏检测
使用如下命令:
valgrind --leak-check=yes ./your-program
3. 详细报告
使用如下命令:
valgrind --leak-check=full --show-leak-kinds=all ./your-program
4. 性能分析
使用如下命令:
valgrind --tool=callgrind ./your-program
5. 多线程错误检测
使用如下命令:
valgrind --tool=helgrind ./your-program
(三)获取帮助
可以通过如下命令获取帮助:
valgrind -h
实际操作如下:

五、 示例
(一)、 示例程序
1、程序代码
假设我们有一个简单的 C 程序 example.c:
include <stdlib.h>
int main() {
int ptr = malloc(10 sizeof(int));
ptr[10] = 0; // 数组越界
free(ptr);
return 0;
}
2、编译该程序
gcc -o example example.c
(二) 使用 Valgrind 检测内存问题
1、运行 Valgrind 并检测内存问题
valgrind --leak-check=full --show-leak-kinds=all ./example
2、输出示例
==12345== Memcheck, a memory error detector
==12345== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12345== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==12345== Command: ./example
==12345==
==12345== Invalid write of size 4
==12345== at 0x4005B4: main (example.c:6)
==12345== Address 0x5204040 is 0 bytes after a block of size 40 alloc'd
==12345== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345== by 0x40059B: main (example.c:5)
==12345==
==12345==
==12345== HEAP SUMMARY:
==12345== in use at exit: 0 bytes in 0 blocks
==12345== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==12345==
==12345== All heap blocks were freed -- no leaks are possible
==12345==
==12345== For lists of detected and suppressed errors, rerun with: -s
==12345== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
六、 工具集
(一)常见工具
Valgrind工具集中包含了多个实用的工具,每个工具都有其特定的功能:
1、Memcheck
内存错误检测器,能够发现开发中绝大多数内存错误使用情况,比如使用未初始化的内存、使用已经释放了的内存、内存访问越界等。它还可以分析热点函数和函数调用流程,帮助优化程序性能。
2、Callgrind
用于分析程序的函数调用关系,收集程序运行时的一些数据,建立函数调用关系图。它还可以有选择地进行cache模拟,并在运行结束时将分析数据写入一个文件。
3、Cachegrind
分析程序的缓存使用情况和缓存命中率,通过模拟处理器缓存的访问情况来统计程序的缓存行使用情况、缓存命中率和缓存失效次数等信息。
4、Helgrind
线程错误检测器,用于检查多线程程序中出现的竞争问题。它寻找内存中被多个线程访问而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,容易导致难以发现的错误。
5、Massif
堆栈分析器,主要用来检查程序中堆栈使用中出现的问题。它能测量程序在堆栈中使用了多少内存,帮助开发者了解块寿命、块利用率和布局效率低下的问题。
此外,Valgrind还提供了其他工具,如DHAT(用于检测堆内存分配和使用情况)等,以满足不同开发者的需求。
(二) 示例:使用 Callgrind 进行性能分析
1. 运行 Callgrind
valgrind --tool=callgrind ./your-program
2. 生成可视化报告
使用 kcachegrind 工具查看生成的性能报告:
kcachegrind callgrind.out.<pid>
七、 常见问题及解决方法
1. 性能影响
Valgrind 会使程序运行变慢,通常比原生运行慢几倍到几十倍。因此,建议在开发和测试阶段使用 Valgrind,而不是在生产环境中。
2. 错误报告过多
如果程序中有大量的第三方库或系统库,可能会产生很多错误报告。可以使用 --gen-suppressions=all 选项生成抑制文件,然后在后续运行中使用 --suppressions=<file> 选项来忽略这些错误。
3. 内存泄漏报告不准确
确保程序在退出前释放所有分配的内存。如果某些内存是故意不释放的(如全局静态变量),可以使用抑制文件来忽略这些报告。
文章正下方可以看到我的联系方式:鼠标“点击” 下面的 “威迪斯特-就是video system 微信名片”字样,就会出现我的二维码,欢迎沟通探讨。