当前位置: 首页 > news >正文

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++软件调试 👈

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
IDEQt 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查看。

    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4、使用Heob分析qt 程序内存泄漏🦧

  1. 打开测试代码,使用MSVC编译器、Debug模式进行编译,保留pdb符号表;

  2. 编译生成可执行程序;

  3. 点击【分析】【Heob】【OK】启动程序进行分析;

  4. 当程序运行后分别点击【泄漏1】【泄漏2】按键,然后退出程序,程序退出后会将分析结果生成位leaks.xml文件,并在调试窗口显示检测到的内存泄漏;

  5. 生成的检测结果会有许多动态库中的误报,可以点击调试窗口上的过滤图标,取消勾选【外部错误】项(如果MSVC版本<=2017则勾选外部错误);

    在这里插入图片描述

  6. 检测结果如下所示,出现两个内存泄漏,大小分别是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&#xff08;26&#xff09; 文章目录 C(Qt)软件调试---内存分析工具Heob&#xff08;26&#xff09;[toc]1、概述&#x1f41c;2、环境配置&#x1fab2;3、功能说明4、使用Heob分析qt 程序内存泄漏&#x1f9a7;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作为一款热门的跨平台开发框架&#xff0c;其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用&#xff0c;包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例&#xff0c;让你轻松掌握这一工…...

Python 第三方库 PyQt5 的安装

目录 前言 PyQt5安装 不同操作系统PyQt5安装 一、Windows 系统 二、macOS 系统 三、Linux 系统&#xff08;以 Ubuntu 为例&#xff09; 安装 PyQt5 可能会遇到的问题 一、环境相关问题 二、依赖问题 三、网络问题 四、安装工具问题 五、运行时问题 六、环境配置问…...

CSS基础也要进行模电实验

盒子阴影 圆角边框已经介绍过哩&#xff0c;现在先介绍一下盒子阴影的效果如何实现 CSS3中新增了盒子阴影&#xff0c;可以使用box-shadow属性为盒子添加阴影 这是固定的语法&#xff1a; text-shadow: h-shadow v-shadow blur color; 它有这些可选的值&#xff1a; 哦。 …...

贴代码框架PasteForm特性介绍之markdown和richtext

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…...

3D Gaussian Splatting 代码层理解之Part3

最后,内容到达了高斯泼溅过程中最有趣的阶段:渲染!这一步可以说是最关键的,因为它决定了模型的真实性。然而,它也可能是最简单的。在本系列的Part 1和Part2,文章演示了如何将 Raw 3D椭球 转换为可渲染的格式,但现在我们实际上必须完成这项工作并渲染到一组固定的像素上。…...

Ceph 中PG与PGP的概述

在Ceph分布式存储系统中&#xff0c;PG&#xff08;Placement Group&#xff09;和PGP&#xff08;Placement Group for Placement purpose&#xff09;是两个至关重要的概念&#xff0c;它们共同决定了数据在集群中的分布和复制方式。以下是关于Ceph中PG和PGP关系的详细解释&a…...

已解决:spark代码中sqlContext.createDataframe空指针异常

这段代码是使用local模式运行spark代码。但是在获取了spark.sqlContext之后&#xff0c;用sqlContext将rdd算子转换为Dataframe的时候报错空指针异常 Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.Nu…...

flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例

flutter字体大小切换案例 小字体&#xff0c;标准字体&#xff0c;大字体&#xff0c;超大字体案例 Android iOS设备带有选择记录 我的flutter项目版本 environment: sdk: ‘>3.4.4 <4.0.0’ 图片案例 pubspec.yaml 添加依赖 # 屏幕尺寸适配 https://github.com/OpenF…...

智慧建造-运用Trimble技术将梦幻水族馆变为现实【上海沪敖3D】

项目概述 西雅图水族馆耗资1.6亿美元对海洋馆进行扩建。该项目包括建造三个大型栖息地&#xff0c;每个建筑物几乎都没有直边&#xff0c;其中一个主栖息地由520立方米混凝土和355吨钢筋组成。特纳建筑公司的混凝土团队通过强大的贸易合作伙伴和创新的数字制造技术&#xff0c;…...

【NOIP提高组】计算系数

【NOIP提高组】计算系数 C语言实现C实现Java实现Python实现 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 给定一个多项式 (ax by)^k &#xff0c;请求出多项式展开后 x^n y^m 项的系数。 输入 共一行&#xff0c;包含 5 个整数&#x…...

IDEA部署AI代写插件

前言 Hello大家好&#xff0c;当下是AI盛行的时代&#xff0c;好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风&#xff0c;然后写实什么的&#xff0c;现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…...

【阅读记录-章节1】Build a Large Language Model (From Scratch)

目录 1. Understanding large language models1.1 What is an LLM?补充介绍人工智能、机器学习和深度学习的关系机器学习 vs 深度学习传统机器学习 vs 深度学习&#xff08;以垃圾邮件分类为例&#xff09; 1.2 Applications of LLMs1.3 Stages of building and using LLMs1.4…...

微服务day08

Elasticsearch 需要安装elasticsearch和Kibana&#xff0c;应为Kibana中有一套控制台可以方便的进行操作。 安装elasticsearch 使用docker命令安装&#xff1a; docker run -d \ --name es \-e "ES_JAVA_OPTS-Xms512m -Xmx512m" \ //设置他的运行内存空间&#x…...

JAVA接入WebScoket行情接口

Java脚好用的库很多&#xff0c;开发效率一点不输Python。如果是日内策略&#xff0c;需要更实时的行情数据&#xff0c;不然策略滑点太大&#xff0c;容易跑偏结果。 之前爬行情网站提供的level1行情接口&#xff0c;实测平均更新延迟达到了6秒&#xff0c;超过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:用计算属性实现搜索框功能

前言&#xff1a; 本文代码使用vue2element UI。 输入框搜索的功能&#xff0c;可以在前端通过计算属性过滤实现&#xff0c;也可以调用后端写好的接口。本文介绍的是通过计算属性对表格数据实时过滤&#xff0c;后附完整代码&#xff0c;代码中提供的是死数据&#xff0c;可…...

抖音热门素材去哪找?优质抖音视频素材网站推荐!

是不是和我一样&#xff0c;刷抖音刷到停不下来&#xff1f;越来越多的朋友希望在抖音上创作出爆款视频&#xff0c;但苦于没有好素材。今天就来推荐几个超级实用的抖音视频素材网站&#xff0c;让你的视频内容立刻变得高大上&#xff01;这篇满是干货&#xff0c;直接上重点&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.…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

负载均衡器》》LVS、Nginx、HAproxy 区别

虚拟主机 先4&#xff0c;后7...