C++(Qt)软件调试---内存分析工具Heob(26)
C++(Qt)软件调试—内存分析工具Heob(26)
文章目录
- C++(Qt)软件调试---内存分析工具Heob(26)
- @[toc]
- 1、概述🐜
- 2、环境配置🪲
- 3、功能说明
- 4、使用Heob分析qt 程序内存泄漏🦧
- 5、使用Heob检测qt 程序野指针/内存越界👓
- 6、使用Heob检测qt 程序空指针/throw抛出异常👕
- 7、使用Heob检测qt 程序重复释放👗
- 8、使用Heob检测qt 程序长生命周期式内存泄漏👙
- 9、相关地址🐐
文章目录
- C++(Qt)软件调试---内存分析工具Heob(26)
- @[toc]
- 1、概述🐜
- 2、环境配置🪲
- 3、功能说明
- 4、使用Heob分析qt 程序内存泄漏🦧
- 5、使用Heob检测qt 程序野指针/内存越界👓
- 6、使用Heob检测qt 程序空指针/throw抛出异常👕
- 7、使用Heob检测qt 程序重复释放👗
- 8、使用Heob检测qt 程序长生命周期式内存泄漏👙
- 9、相关地址🐐
| 更多精彩内容 |
|---|
| 👉内容导航 👈 |
| 👉C++软件调试 👈 |
1、概述🐜
绝大部分的文章都说Heob是一个内存泄漏分析工具,其实Heob只是内存泄漏分析功能比较突出,实际上Heob可以分析很多内存问题。
Heob是一个Windows下检测缓冲区溢出(野指针、空指针、内存越界、重复释放、异常捕获等)和内存泄漏的工具,集成到Qt Creator中,功能强大,简单容易上手。
支持MSVC和MinGW编译器编译的程序内存泄漏检测;
支持32位和64位程序;
不支持Linux;
支持设置过滤内存泄漏字节大小;
支持异常处理;
支持与Qt调试器、事后调试器联动;
支持将分析结果导出位xml文件,后续通过加载xml文件查看分析结果;
Qt Creator支持4.6以上版本,低版本没有这个功能,可以自行安装高版本的QtCreator(注意:不是Qt版本,是IDE版本)。
处理速度块,占用资源少。
在Qt中使用Heob分析内存泄漏有4种用法:
方法1: 使用Heob分析MSVC编译生成的程序,对于 PDB 调试信息,使用 dbghelp.dll,速度块;
方法2: 使用Heob分析MinGW编译生成的程序, 对于DWARF 调试信息 (gcc) ,需要下载dwarfstack.dll库到Heob路径下才可以使用,性能会低很多;
- 方法3: 使用Heob分析MinGW编译生成的程序,通过cv2pdb将DWARF 转成PDB进行分析,性能和分析MSVC编译的程序差不多。
- 方法4: 命令行运行。
注意:
- MSVC版本<=2017时,Heob检测会出现误报,将内存泄漏包位外部错误的内存泄漏,所以如果使用的编译器版本比较低,过滤设置时就需要勾选上外部错误 项;
- 对MinGW和MSVC支持不同,有些情况使用MSVC编译器可以检测出来,使用MinGW检测不出来,有些情况相反。
- 运行Heob前需要保证代码已经完成编译并生成了可执行程序。
演示环境:
| 环境 | 版本 |
|---|---|
| 系统 | Windows11 |
| 开发环境 | Qt5.9、Qt5.12.12、Qt5.14.2、Qt6.8 |
| IDE | Qt Creator 5、Qt Creator 10、Qt Creator 14、Qt Creator 15 |
| 编译器 | mingw730_64、mingw1310_64、MSVC2015-64、MSVC2017-64、MSVC2022-64 |
| 分析工具 | Heob 4.0 |
| 依赖库 | dwarfstack 2.2 |
2、环境配置🪲
-
下载Heob 4.0和dwarfstack 2.2 解压到同一个文件夹中;
-
打开Qt Creator,选中【分析】【Heob】;

-
打开Heob窗口后点击【浏览】选择Heob路径,然后点击右下角图标保存配置。

-
创建一个Qt工程,测试代码如下所示
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}class Test
{
public:Test(){p = new int;}private:int* p;
};/*** @brief 内存泄漏1*/
void Widget::on_pushButton_clicked()
{Test* test = new Test();free(test);
}void fun()
{for(int i = 0; i < 1024; i++){int*p = new int[1000];qDebug() << p[1];}
}
/*** @brief 内存泄漏2*/
void Widget::on_pushButton_2_clicked()
{fun();
}/*** @brief 野指针1*/
void Widget::on_pushButton_3_clicked()
{int* p = new int;delete p;*p = 123;
}/*** @brief 野指针2*/
void Widget::on_pushButton_4_clicked()
{int* p;*p = 123;
}/*** @brief 空指针*/
void Widget::on_pushButton_5_clicked()
{int* p = nullptr;*p = 123;
}/*** @brief 内存越界*/
void Widget::on_pushButton_6_clicked()
{int*p = new int[12];p[123] = 123;p[12] = 1234;delete[] p;
}/*** @brief 重复释放*/
void Widget::on_pushButton_7_clicked()
{int*p = new int[12];p[1] = 123;delete[] p;delete[] p;
}/*** @brief 抛出异常*/
void Widget::on_pushButton_8_clicked()
{throw 123;
}/*** @brief 成员数组添加数据*/
void Widget::on_pushButton_9_clicked()
{for(int i = 0; i < 10000; i++){m_list.append(new int);qDebug() << i;}
}QList<int*> g_list;
/*** @brief 全局数组添加数据*/
void Widget::on_pushButton_10_clicked()
{for(int i = 0; i < 10000; i++){g_list.append(new int);qDebug() << i;}
}/*** @brief 释放内存*/
void Widget::on_pushButton_11_clicked()
{for(int i = 0; i < m_list.count(); i++){delete m_list[i];}for(int i = 0; i < g_list.count(); i++){delete g_list[i];}m_list.clear();g_list.clear();QMessageBox::about(this, "注意!", QString("已经释放内存:%1 %2").arg(m_list.count()).arg(g_list.count()));
}

3、功能说明
- 详细功能说明可以打开命令行,使用
heob.exe -H命令查看;
如图所示:

-
点击【新建/删除】可以创建新的配置文件;
-
点击右下角软盘图标可以保存配置,配置文件保存在
C:\Users\MHF\AppData\Roaming\QtProject\QtCreator.ini文件中; -
点击【OK】开始进行分析。
-
Heob Path: 下载解压的Heob.exe文件路径;
-
XML output file: 生成的xml文件名称,使用的相对路径,在可执行程序路径下,后续可通过【调试】窗口中的文件夹图标加载生成的xml文件;

-
Handle exceptions: 设置出现异常时的处理方式
- 设置为On则使用Heob处理,出现异常时程序退出,在调试窗口显示出现异常的信息;
- 设置为Off则在出现异常时,会使用事后调试器进行调试。
- 设置为Only则禁用所有Heob功能,除了安装异常处理程序。如果应用程序崩溃,则只显示崩溃的堆栈跟踪,不检测内存泄漏。因此,当在控制台上使用Heob或为子进程运行Heob时,此选项非常有用。

-
Run with debugger: 勾选上后会以Debug调试模式运行,当出现异常(例如空指针野指针)时会触发断点,定位到出现异常的位置;

- Raise breakpoint exception on error: 表示出现异常时触发断点,(主要用于重复释放)
- 如果没勾选,则出现重复释放、内存越界等问题时,不会触发异常断点,会将检测结果写入文件;
- 如果勾选上后,并且勾选了Run with debugger,则出现重复释放、内存越界等问题时,将会触发异常断点;

- Page protection: 这个功能更适合用于检测内存越界、野指针;
- 选择OFF时更适合检测内存泄漏;
- 选择After后会在分配的内存块末尾设置一个保护页,当访问到这个保护页时就会触发异常,从而识别出野指针、内存越界;
- 选择Before则会再分配的内存块前设置一个保护页;
- 这个功能会消耗内存、降低检查速度,建议仅用于64位或短时间运行的程序。

- Freed memory protection: 这个功能会增加释放内存保护功能,已经释放的内存就不会再被使用,对于检测野指针、重复释放问题有用,但是会大量消耗内存。
- Leak details: 这个选项用于设置程序退出时融合处理收集到的内存泄漏数据,不同的设置影响分析结果和处理速度;
- None:表示不收集内存泄漏数据,所以退出时速度最快;
- Simple:表示将所有未释放的内存写入结果文件,速度最慢,生成的xml文件也最大,所有内存泄漏分析结果都会被记录为
16 bytes in 1 blocks are lost in loss record 196 of 209 (#2513),无法通过过滤器进行过滤; - Detect Leak Types:会记录所有确定的直接内存泄漏、间接内存泄漏到文件中,速度会快一些;
- Detect Leak Types (Show Reachable):除了记录所有确定的直接内存泄漏、间接内存泄漏到文件中,还会将可能存在内存泄漏的结果记录到文件中,可以通过过滤器中【可能的内存泄漏】选项过滤;
- Fuzzy Detect Leak Types:选择模糊检测泄漏类型来标记内存块,或者它们是否引用了任何地址。当使用一些自定义分配器(例如:ffmpeg的av_malloc())时,此选项很有用,检测结果最少,只保留最有可能内存泄漏的记录,速度快,生成的文件小;
- Detect Leak Types (Show Reachable) :与Fuzzy Detect Leak Types类似,不过会将其它的记录认为是可能存在的内存泄漏,也会记录到文件中,可以通过过滤器中【可能的内存泄漏】选项过滤。

- Minimum leak size: 设置记录内存泄漏的最小字节数,低于设置值的内存泄漏不会被记录;

-
Control leak recording: 控制记录内存泄漏的开关、记录时间段等,更加灵活的记录分析内存泄漏的功能(例如记一个数组不断添加堆内存数据,很长一段时间才会释放一次,这种就是特殊情况的内存泄漏,就可以通过n/f快捷键来控制检测);
- OFF:关闭终端,始终开启内存泄漏记录;
- On (Start Disabled):打开终端,Heob启动时不记录内存泄漏,可在终端中进行控制;
- On (Start Enabled):打开终端,Heob启动时就开始记录内存泄漏,并且可在终端中进行控制。

-
Extra arguments: 用于输入运行其它Heob参数,例如输入
-vleaks.svg会将检测结果生成svg矢量图;- 更多Heob参数使用命令行
Heob64.exe -H查看。

- 更多Heob参数使用命令行



4、使用Heob分析qt 程序内存泄漏🦧
-
打开测试代码,使用MSVC编译器、Debug模式进行编译,保留pdb符号表;
-
编译生成可执行程序;
-
点击【分析】【Heob】【OK】启动程序进行分析;
-
当程序运行后分别点击【泄漏1】【泄漏2】按键,然后退出程序,程序退出后会将分析结果生成位leaks.xml文件,并在调试窗口显示检测到的内存泄漏;
-
生成的检测结果会有许多动态库中的误报,可以点击调试窗口上的过滤图标,取消勾选【外部错误】项(如果MSVC版本<=2017则勾选外部错误);

-
检测结果如下所示,出现两个内存泄漏,大小分别是409600字节和16字节。


5、使用Heob检测qt 程序野指针/内存越界👓
- 打开Heob窗口;
- 将Page protection选为【After】或者【Before 】;
- 点击开始检测,运行野指针代码就可以成功捕获到野指针异常。
- 由于野指针、内存越界都是不可恢复的异常,所以检测到这类异常后会直接终止Heob。

6、使用Heob检测qt 程序空指针/throw抛出异常👕
- 打开Heob窗口;
- 使用默认设置;
- 点击开始检测,运行野指针代码就可以成功捕获到空指针、抛出异常。
- 由于空指针异常无法恢复,检测到后会终止Heob;
- 如果throw抛出异常后没有被try捕获,则会被Heob检测到,并触发终止,如果被try捕获,则Heob无法检测。

7、使用Heob检测qt 程序重复释放👗
- 打开Heob窗口;
- 勾选Raise breakpoint exception on error: 表示出现异常时触发断点,如果不勾选就只会保存到检测结果;
- 再勾选Run with debugger ,在出现重复释放异常时,就会触发断点,进入调试。

8、使用Heob检测qt 程序长生命周期式内存泄漏👙
这里的长生命周期式内存泄漏不同于普通内存泄漏使用new分配了而没有delete;
长生命周期内存泄漏指使用new分配了内存,过了很长时间才会delete,例如成员指针、全局变量、静态变量等;
这类内存泄漏会更加难以排查,也容易造成严重问题。
测试方法1: 无法检测到长生命周期内存泄漏
- 打开Heob进行检测;
- 点击按键,向成员数组中new大量变量;
- 过一段时间后再释放成员数组中的所有内存;
- 无法检测到出现内存泄漏;

测试方法1: 无法检测到长生命周期内存泄漏
-
打开Heob窗口;
-
如下图所示,选择Detect Leak Types(不必须),避免文件写入太多内存,检测大小设置为500字节(不必须),选择On(Start Disabled),在程序启动前不记录,在运行过程中通过终端命令行控制开始/结束记录的时机;

-
点击【OK】启动Heob;
-
程序运行后按下
n键开始记录; -
然后在程序中分别给成员数组、全局数组分配内存;
-
在终端按下
f键停止记录,并按下s键将当前内存泄漏分析结果写入文件; -
然后点击按键释放数组分配的内存;
-
退出程序后就可以看见检测到的内存泄漏了。

9、相关地址🐐
- Heob
- 下载dwarfstack.dll
- 通过cv2pdb将DWARF 转成PDB
- Heob | Qt Creator Documentation
- Detect memory leaks with Heob | Qt Creator Documentation
相关文章:
C++(Qt)软件调试---内存分析工具Heob(26)
C(Qt)软件调试—内存分析工具Heob(26) 文章目录 C(Qt)软件调试---内存分析工具Heob(26)[toc]1、概述🐜2、环境配置🪲3、功能说明4、使用Heob分析qt 程序内存泄漏🦧5、使用Heob检测qt 程序野指针…...
Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)
目录 一、String字符串类型介绍 二、常见命令 1、SET 2、GET 3、MGET 4、MSET 使用MGET 和 使用多次GET的区别 5、DEL 6、SETNX SET、SET NX和SET XX执行流程 7、INCR 8、INCRBY 9、DECR 10、DECYBY 11、INCRBYFLOAT 12、APPEND 13、GETRANGE 14、SETRANGE …...
Flutter中的Material Theme完全指南:从入门到实战
Flutter作为一款热门的跨平台开发框架,其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用,包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例,让你轻松掌握这一工…...
Python 第三方库 PyQt5 的安装
目录 前言 PyQt5安装 不同操作系统PyQt5安装 一、Windows 系统 二、macOS 系统 三、Linux 系统(以 Ubuntu 为例) 安装 PyQt5 可能会遇到的问题 一、环境相关问题 二、依赖问题 三、网络问题 四、安装工具问题 五、运行时问题 六、环境配置问…...
CSS基础也要进行模电实验
盒子阴影 圆角边框已经介绍过哩,现在先介绍一下盒子阴影的效果如何实现 CSS3中新增了盒子阴影,可以使用box-shadow属性为盒子添加阴影 这是固定的语法: text-shadow: h-shadow v-shadow blur color; 它有这些可选的值: 哦。 …...
贴代码框架PasteForm特性介绍之markdown和richtext
简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…...
3D Gaussian Splatting 代码层理解之Part3
最后,内容到达了高斯泼溅过程中最有趣的阶段:渲染!这一步可以说是最关键的,因为它决定了模型的真实性。然而,它也可能是最简单的。在本系列的Part 1和Part2,文章演示了如何将 Raw 3D椭球 转换为可渲染的格式,但现在我们实际上必须完成这项工作并渲染到一组固定的像素上。…...
Ceph 中PG与PGP的概述
在Ceph分布式存储系统中,PG(Placement Group)和PGP(Placement Group for Placement purpose)是两个至关重要的概念,它们共同决定了数据在集群中的分布和复制方式。以下是关于Ceph中PG和PGP关系的详细解释&a…...
已解决:spark代码中sqlContext.createDataframe空指针异常
这段代码是使用local模式运行spark代码。但是在获取了spark.sqlContext之后,用sqlContext将rdd算子转换为Dataframe的时候报错空指针异常 Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.Nu…...
flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例
flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例 Android iOS设备带有选择记录 我的flutter项目版本 environment: sdk: ‘>3.4.4 <4.0.0’ 图片案例 pubspec.yaml 添加依赖 # 屏幕尺寸适配 https://github.com/OpenF…...
智慧建造-运用Trimble技术将梦幻水族馆变为现实【上海沪敖3D】
项目概述 西雅图水族馆耗资1.6亿美元对海洋馆进行扩建。该项目包括建造三个大型栖息地,每个建筑物几乎都没有直边,其中一个主栖息地由520立方米混凝土和355吨钢筋组成。特纳建筑公司的混凝土团队通过强大的贸易合作伙伴和创新的数字制造技术,…...
【NOIP提高组】计算系数
【NOIP提高组】计算系数 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 给定一个多项式 (ax by)^k ,请求出多项式展开后 x^n y^m 项的系数。 输入 共一行,包含 5 个整数&#x…...
IDEA部署AI代写插件
前言 Hello大家好,当下是AI盛行的时代,好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风,然后写实什么的,现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…...
【阅读记录-章节1】Build a Large Language Model (From Scratch)
目录 1. Understanding large language models1.1 What is an LLM?补充介绍人工智能、机器学习和深度学习的关系机器学习 vs 深度学习传统机器学习 vs 深度学习(以垃圾邮件分类为例) 1.2 Applications of LLMs1.3 Stages of building and using LLMs1.4…...
微服务day08
Elasticsearch 需要安装elasticsearch和Kibana,应为Kibana中有一套控制台可以方便的进行操作。 安装elasticsearch 使用docker命令安装: docker run -d \ --name es \-e "ES_JAVA_OPTS-Xms512m -Xmx512m" \ //设置他的运行内存空间&#x…...
JAVA接入WebScoket行情接口
Java脚好用的库很多,开发效率一点不输Python。如果是日内策略,需要更实时的行情数据,不然策略滑点太大,容易跑偏结果。 之前爬行情网站提供的level1行情接口,实测平均更新延迟达到了6秒,超过10只股票并发请…...
使用Axios函数库进行网络请求的使用指南
目录 前言1. 什么是Axios2. Axios的引入方式2.1 通过CDN直接引入2.2 在模块化项目中引入 3. 使用Axios发送请求3.1 GET请求3.2 POST请求 4. Axios请求方式别名5. 使用Axios创建实例5.1 创建Axios实例5.2 使用实例发送请求 6. 使用async/await简化异步请求6.1 获取所有文章数据6…...
Vue2+ElementUI:用计算属性实现搜索框功能
前言: 本文代码使用vue2element UI。 输入框搜索的功能,可以在前端通过计算属性过滤实现,也可以调用后端写好的接口。本文介绍的是通过计算属性对表格数据实时过滤,后附完整代码,代码中提供的是死数据,可…...
抖音热门素材去哪找?优质抖音视频素材网站推荐!
是不是和我一样,刷抖音刷到停不下来?越来越多的朋友希望在抖音上创作出爆款视频,但苦于没有好素材。今天就来推荐几个超级实用的抖音视频素材网站,让你的视频内容立刻变得高大上!这篇满是干货,直接上重点&a…...
spring-cache concurrentHashMap 自定义过期时间
1.自定义实现缓存构建工厂 import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap;import lombok.Getter; import lombok.Setter; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

