Linux系统使用valgrind分析C++程序内存资源使用情况

devtools/2024/11/26 17:54:25/

内存占用是我们开发的时候需要重点关注的一个问题,我们可以人工根据代码推理出一个消耗内存较大的函数,也可以推理出大概会消耗多少内存,但是这种方法不仅麻烦,而且得到的只是推理的数据,而不是实际的数据。

我们可以使用工具来分析实际的内存消耗情况,分析较严重的内存消耗点,然后想办法修改。这篇文章我们就来聊一下在Linux系统中怎么使用valgrind分析C++程序内存资源使用情况。当然,在分析内存使用情况之前建议先解决内存泄漏问题,我们之前也介绍过怎么分析内存泄漏。

valgrind是一个工具组,valgrind里的massif工具可以用来分析内存使用情况,帮助识别程序中内存占用高的部分。

我们来看一个示例程序

#include <iostream>
#include <thread>
#include <chrono>
#include <string.h>void FuncA()
{void *p = malloc(1024);memset(p, 'a', 1024); // 填充一些数据,防止内存处于伪分配的状态free(p);
}void FuncB()
{void *p = malloc(1024 * 3);memset(p, 'a', 1024 * 3);free(p);
}void FuncC()
{void *p = malloc(1024 * 6);memset(p, 'a', 1024 * 6);free(p);
}int main()
{FuncA();std::this_thread::sleep_for(std::chrono::milliseconds(10));FuncB();std::this_thread::sleep_for(std::chrono::milliseconds(10));FuncC();std::this_thread::sleep_for(std::chrono::milliseconds(10));return 0;
}

这个程序很简单,所以我们完全可以直接分析出来实际内存使用情况,但是这里我们来看一下怎么用工具分析。

先执行命令g++ -g ./main.cpp -o main将前面这段代码构建成可执行程序。

安装valgrind可以执行命令apt install valgrind直接安装,然后执行命令valgrind --version查看是否已经正常安装。

valgrind安装完成之后我们就可以执行命令valgrind --tool=massif --time-unit=ms ./main启动分析了,解释一下这条命令中的参数:

  • --tool=massif表示使用massif工具。
  • --time-unit=ms表示按照时间片抓取快照,还可以指定按照程序执行的指令数或者内存的变化量抓取快照。

这条命令执行完成后会生成一个分析结果文件
在这里插入图片描述

这个分析结果文件的文件名默认就是上图中的格式,后缀是进程号。

然后我们分析一下这个分析结果文件,valgrind有个自带的工具叫ms_print可以用来打开这种分析结果文件,比如执行命令ms_print ./massif.out.3679就可以查看了。

但是这个可视化效果不好,我们可以使用另外一个工具massif-visualizer来分析,这个工具可以以火焰图的形式将结果文件展示出来。

可以执行命令apt install massif-visualizer安装massif-visualizer工具,然后执行命令massif-visualizer --version确认是否已经正常安装。

安装完成之后我们就可以使用massif-visualizer分析了,比如执行命令massif-visualizer ./main.massif.out打开结果文件,这个工具的具体用法可以自己研究下
在这里插入图片描述

上面这种方法只能在程序执行完之后才能获取到分析结果文件,我们来看一下怎么在程序执行的过程中获取分析结果文件,需要使用gdb配合。

修改一下代码

#include <iostream>
#include <thread>
#include <chrono>
#include <string.h>void FuncA()
{void *p = malloc(1024);memset(p, 'a', 1024); // 填充一些数据,防止内存处于伪分配的状态free(p);
}void FuncB()
{void *p = malloc(1024 * 3);memset(p, 'a', 1024 * 3);free(p);
}void FuncC()
{void *p = malloc(1024 * 6);memset(p, 'a', 1024 * 6);free(p);
}int main()
{FuncA();std::this_thread::sleep_for(std::chrono::milliseconds(10));FuncB();std::this_thread::sleep_for(std::chrono::milliseconds(10));FuncC();std::this_thread::sleep_for(std::chrono::milliseconds(10));getchar();return 0;
}

可以看到只是多了一个getchar(),用这种方式来让程序不要直接退出。执行命令g++ -g ./main.cpp -o main构建一下。

执行命令valgrind --vgdb=yes --tool=massif --time-unit=ms --massif-out-file=main.massif.out ./main启动分析,解释一下这条命令中的参数:

  • –vgdb=yes表示开启gdbserver。
  • –massif-out-file=main.massif.out表示指定生成的分析结果文件名为main.massif.out。

在这里插入图片描述

可以看到程序正在执行,前面那个数字是进程号,等下需要用到。

然后我们另外开启一个命令窗口,执行命令gdb ./main启动gdb调试。
在这里插入图片描述

然后在gdb中启动远程调试,比如执行命令target remote | /usr/bin/vgdb --pid=6004,pid就是前面启动分析时的那个。
在这里插入图片描述

然后在gdb中执行命令monitor all_snapshot main.massif.vgdb.out,这条命令可以驱动valgrind使用当前所有快照生成一个文件名为main.massif.vgdb.out的分析结果文件,在程序执行完之后也会生成一个分析结果文件。
在这里插入图片描述

需要注意的是在gdb中远程调试时进程会阻塞,可以在gdb中使用命令c让程序继续执行,就是gdb正常调试时的指令。

如果这篇文章对你有帮助,别忘了关注我啊,可能我还会写出更多对你有帮助的文章


http://www.ppmy.cn/devtools/137178.html

相关文章

Android res复制脚本

./copy.sh A路径 B路径 文件名 key ./copy.sh A_res B_res strings.xml hello 将A_res文件为strings.xml中的hello&#xff0c;复制到项目B_res文件为strings.xml中 #!/bin/bash# 检查输入的参数数量 if [ "$#" -ne 4 ]; thenecho "用法: $0 <源路径> &l…

基于微信小程序的空巢老人健康管理系统

摘 要 随着社会老龄化程度不断加深&#xff0c;空巢老人的健康管理成为一个日益重要的问题。为了更好地关注和管理空巢老人的健康状况&#xff0c;本文利用Spring Boot框架和MySQL数据库&#xff0c;结合微信小程序等技术&#xff0c;设计并实现了一套基于微信小程序的空巢老人…

Android adb shell dumpsys audio 信息查看分析详解

Android adb shell dumpsys audio 信息查看分析详解 一、前言 Android 如果要分析当前设备的声音通道相关日志&#xff0c; 仅仅看AudioService的日志是看不到啥日志的&#xff0c;但是看整个audio关键字的日志又太多太乱了&#xff0c; 所以可以看一下系统提供的一个调试指令…

【智能制造-43】机器人导出的轴配置问题

机器人导出的轴配置问题通常指的是机器人在执行运动指令时&#xff0c;机器人TCP无法按照指定的轴配置方案到达目标点&#xff0c;或者轴配置监督被触发的情况。‌ 这里提到的轴配置方案和目标点等信息&#xff0c;都是存储在位置数据&#xff08;robotarget&#xff09;中的。…

开源客户关系管理平台EspoCRM

简介 什么是 EspoCRM &#xff1f; EspoCRM 是一个开源的客户关系管理&#xff08;CRM&#xff09;平台&#xff0c;旨在帮助组织建立和维护良好的客户关系。它提供了多种工具&#xff0c;用于存储、组织和管理潜在客户、联系人、销售机会、营销活动和支持案例等业务信息&…

5种常见的k8s云原生数据管理方案详解

Kubernetes&#xff08;K8s&#xff09;是云原生架构的核心组件&#xff0c;提供高效的容器编排和管理功能。在数据存储方面&#xff0c;K8s通过PersistentVolumes&#xff08;PV&#xff09;和PersistentVolumeClaims&#xff08;PVC&#xff09;机制实现数据持久化&#xff0…

[C++]了解内置类型升级

内置类型升级 1.调用模板T时&#xff0c;为什么可以使用T()类型的匿名对象来传参2.内置类型被升级成为类后的使用事项 1.调用模板T时&#xff0c;为什么可以使用T()类型的匿名对象来传参 当我们在定义或声明一个函数时&#xff0c;如果想使用模板T类型的默认构造&#xff08;例…

Git Github Gitlab与Gitee的关系

Git是代码版本管理工具 -------项目通过Git可以切换到任意代码版本 Github和Gitee是基于Git技术构建的远程仓库网站 -------可以将你的代码仓库提交上去保存 GitHub与Gitee的区别 -------前者是国外建立,资源更丰富,后者是国内建立,免费功能更多 Gitlab和Github功能类似 …