Ubuntu20.04使用valgrind进程内存分析
一、前言
Valgrind是linux环境下开发应用程序时用于内存调试和性能分析的工具集,其中Memcheck工具可以用来检查C/C++程序中的内存操作错误。本文列举了几种常见的内存操作错误以及Memcheck工具的检测结果,其中包括以下几种类型:
- 使用未初始化的内存
- 内存读写越界
- 内存覆盖
- 读写已经释放的内存
- 内存泄露
文章内容主要分为四个部分,valgrind工具的下载与安装、实例分析、常用选项说明和suppressing errors的设置。通过这四部分的学习,读者可以基本掌握valgrind工具的内存调试方法。
二、下载与安装
在官网https://valgrind.org/downloads/上下载软件,目前最新版本是Valgrind 3.20.0。
然后按照下面的命令解压安装
sudo apt-get install automake sudo apt-get install autoconf tar -jxvf valgrind-3.20.0.tar.bz2 cd valgrind-3.20.0 ./autogen.sh ./configure --prefix=/usr/local/valgrind //根据自己的需要设置安装目录 make -j4 sudo make install
注意:需要把valgrind的bin目录路径添加到环境变量PATH中,打开~/.bashrc文件,在最后一行加入
PATH=${PATH}:/usr/local/valgrind/bin
然后刷新环境变量:
source ~/.bashrc
因为不设置环境变量,你会找不到valgrind指令:
三、valgrind实例分析
推荐阅读官方文档:https://valgrind.org/docs/manual/valgrind_manual.pdf
3.1 生成可执行文件
在makefile中增加调试模式的配置,由于在debug状态下推理出的问题多于release状态下,因此最好切换到debug进行valgrind检测。或者gcc在编译源程序时需要加上-g参数。
3.2 启动被测试的可执行文件
valgrind 命令的基本格式为:valgrind [base option] --tool=<tool name> [tool option] your-program [program options]
通过valgrind启动可执行文件的方式如下(在当前目录情况下):
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes -v --log-file="memcheck.txt" ./executable_file
注意:这里我将所有信息保存在了日志文件中,以便分析!
3.3 错误信息分析
Valgrind工具会在可执行文件执行过程中顺序输出检测到的错误信息。下面分段介绍可执行文件的测试结果,其中双斜线开头的为注释信息。
工具相关信息:
==248067== Memcheck, a memory error detector ==248067== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==248067== Using Valgrind-3.20.0-5147d671e4-20221024 and LibVEX; rerun with -h for copyright info ==248067== Command: ./analysis_service ==248067== Parent PID: 222425
第一个内存错误:使用了未初始化的变量
四、Linux下如何确定内存泄露(补充)
在 Linux 环境的 C/C++ 开发中,当每次只是发生几个字节的内存泄露时,可以写一段测试内存泄露的代码来确认。而当代码中发生可见的大量的内存泄露问题时,可以使用 shell 命令来确认:
- ps 命令
- top 命令
- free 命令
- cat /proc/meminfo 或 cat /proc/$pid/status 命令
4.1 ps 命令
ps 命令用来列出系统中当前正在运行的那些进程,列出的是当前那些进程的快照,就是执行 ps 命令的那个时刻的那些进程。确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等。
ps 命令为我们提供了进程的一次性的查看,它所提供的查看结果并不动态连续的;如果想对进程实时监控,应该用 top 命令。
常用的命令如:
ps -ef | grep 进程关键字 //查看指定进程的信息 ps -aux // 列出当前内存中的所有进程 ps aux --sort=%mem(或者 ps aux --sort %mem) //按照内存占用率的升序排序 ps aux --sort=-%mem (或者 ps aux --sort -%mem) //按照内存占用率降序排序 ps aux | grep -e test //打印含义test关键字的进程 ps -aux | grep -E "test|PID" //打印 包含test关键字的进程信息
4.2 top 命令
top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows 的任务管理器。通常用来观察 CPU 或 内存的占用情况。
top 命令使用如下:
top -d -3 //3s 显示一次 top -p 1921 //显示进程号为 1921 的进程的信息
4.3 free 命令
free 命令可以显示当前系统内存使用情况,主要用于确定设备是否存在内存泄漏。free 命令中的信息都来自于 /proc/meminfo 文件。
默认情况下,即在没有选项的情况下,free 命令显示内存的使用信息。默认按照 k(b) 的计数单位统计。
free 命令使用如下:
free -s 3:表示每隔 3 秒打印一次内存信息
注意:可以通过在设备启动和运行一段时间后,使用 free 命令查看 已使用内存(used) 的大小并进行对比,如果运行一段时间后 used内存 有很明显的增大,那很有可能是存在内存泄漏。
4.4 cat /proc/meminfo 或 cat /proc/$pid/status 命令
cat /proc/meminfo //用来查看 Linux 系统的内存使用情况。 cat /proc/$pid/status //用来查看某个进程的内存使用信息。
查看 RAM 使用情况最简单的方法是通过 /proc/meminfo。这个动态更新的虚拟文件实际上是许多其他内存相关工具 (如 free / ps / top 命令) 等的组合显示。
注意:这个文件显示的单位是 kB 而不是 KB,1kB = 1000B,但是实际上应该是KB,1KB=1024B。这个显示是不精确的,是一个已知的没有被更正的历史遗留问题。因为很多程序依赖这个文件查看内存使用的是kB字符
如上所示,解释一下重要字段如下:
- MemTotal: 应用可以使用的内存总数
- MemFree: 当前空闲的内存数目
- MemAvailable: 可用内存(MemFree + 可回收的内存),系统中有些内存虽然已被使用,但是可以回收,如cache、buffer、slab都有一部分可以回收。
- Buffers: 用来给文件做缓存大小
其他暂不做解释。