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.…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

