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

Visual Studio下的内存安全检测:CRT 内存泄漏 AddressSanitizer

Visual Studio下的内存安全检测:CRT 内存泄漏 & AddressSanitizer

前言

​ 笔者之前有一篇博客专门介绍了GNU工具链下的gcc如何启动AddressSanitizer来检查内存安全检查

AddressSanitizer 实践:几个常见的错误-CSDN博客

​ 但是我发现,很多朋友包括我自己之后的工作是在Windows上做的,为此就有必要单独拉出来谈一谈Visual Studio(或者是使用MSVC编译器的命令行)是如何检查我们的内存安全的。这里我们列出来三个渠道。笔者比较建议第二个来检查内存泄露,第三个检查检测越界和 Use-after-free等经典内存误用问题。

  1. 使用 CRT Debug Heap 检测内存泄漏;
  2. 使用 Diagnostic Tools → Memory Usage 分析堆快照和分配调用栈;
  3. 了解 AddressSanitizer 检测越界和 Use-after-free。

内存泄漏检测(CRT Debug Heap)

​ Microsoft C Runtime自己就有Debug插桩机制来检查我们的内存安全。如果您不太相信,您可以这样做:

#define _CRTDBG_MAP_ALLOC // 定义在待检查文件的开头#include <crtdbg.h> // 这个头文件要被包含进来,从而使用代码层次上的插桩#include <cstdlib>
#include <iostream>
#include <cstring>// CRT Debug要在运行期启动,这不奇怪,都是C RunTime提供的机制了,自然运行期执行代码对不对?
void enable_memory_debug() {int dbgFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);dbgFlags |= _CRTDBG_LEAK_CHECK_DF;dbgFlags |= _CRTDBG_ALLOC_MEM_DF;_CrtSetDbgFlag(dbgFlags);// 强制 CRT 报告输出到 stdout, 下面这几步至少在VS2026是必须要做的_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
}int main() {enable_memory_debug();char* p = new char[10];strcpy_s(p, 10, "Hello!");std::cout << "Expected to trigger the overflow check!";   
}

​ 很好,到这里了,程序一结束,我们的程序尾巴就会打印内从,如下所示

Detected memory leaks!
Dumping objects ->
{195} normal block at 0x00000246134FADC0, 10 bytes long.Data: <Hello!    > 48 65 6C 6C 6F 21 00 CD CD CD
Object dump complete.

​ 这就对了,但是您有没有发现,他只是说明了咱们的内存泄露是如何的,但是完全没说在哪里泄露了。这是没有意义的。所以,我们需要费劲的写下这段代码

#ifdef _DEBUG#define DEBUG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )#define new DEBUG_NEW
#endif

​ 这段代码的意思是——将new重新定义为——插桩了文件所在地址和行数的new,然后定义回去。

main.cpp(36) : {195} normal block at 0x00000246134FADC0, 10 bytes long.

​ 现在我们的信息就多出来了!

值得一提的是,犯不着等到程序结束让程序自动触发打印检查,只需要我们调用_CrtDumpMemoryLeaks();这个函数就会打印我们的泄露情况。

在特定分配断点

​ 但是好像还是不够方便。有时候重定向new看起来怪怪的,我们改变了程序的分配内存行为,有没有比较低侵入的办法呢?有。您有注意到{195} normal block at 0x00000246134FADC0, 10 bytes long.的195没?注意到的话,这就是我们内存分配块的分配序号。这个时候,我们可以在代码的开头(需要注意的是,是在enable_debug()操作之后做,以及最好是任何new之前做。)写下

_CrtSetBreakAlloc(195);

F5 调试,程序会在该次分配断下,这个时候,我们就检查调用堆栈,看看到底是哪一行的分配我们忘记释放了。


Diagnostic Tools:堆快照分析

​ 您会发现(笔者实际上做的时候就有感觉了),方式一比较原始,而且我们要做的处理非常繁杂,甚至还需要专门准备开启打印的内容,其实适合的是自己代码就有意检查的模块部分,但是我相信大部分情况下大家都是在救急。期望赶快找到是哪里程序的内存分配行为错误了。这个时候Diagnostic Tools就显得十分的重要的了。

​ 请注意,建议先打开断点,随便在main的起头把断点上了,然后Debug → Windows → Show Diagnostic Tools,注意,内存诊断要开启,笔者第一次做没有开启就发现不允许拍内存快照,之后,我们需要做的是

  1. 运行程序到想分析的点,点击 Take snapshot(Snapshot #1);
  2. 继续运行,到你认为程序一个功能职责结束的地方拍 Snapshot #2;
  3. 查看 Diff:增长对象表示潜在泄漏。

这是笔者的一个截图,您能看到右下角的位置上,本来我们预期是内存全部释放的地方上却上升了0.06KB(约10B,恰好就是我们泄露的点)
在这里插入图片描述

当然,点击对象类型的项目,你就会自动跳转到到底是谁干的分配了,这里不再赘述。

如果我们添加了delete[] p,那就是用完后内存就被归还了。再拍两次快照,对比差异接近 0,泄漏被修复。
在这里插入图片描述


3. AddressSanitizer(ASan)

​ 如果对AddressSanitizer还不知道是啥的,笔者建议您去我开头提到的博客看看

AddressSanitizer 实践:几个常见的错误-CSDN博客

​ Visual Studio下开启并不困难,只需要勾选:

  • Project → Properties → C/C++ → General → Enable Address Sanitizer = Yes (/fsanitize=address)(Tips:中文的话是启用地址擦除系统,找了好久)
  • Debug x64 模式,Clean rebuild 项目。

3.2 越界示例

char* p = new char[8];
for (int i = 0; i < 12; ++i) p[i] = 'A'; // OOB
delete[] p;

3.3 Use-after-free 示例

char* p = new char[16];
strcpy_s(p, 16, "hello asan");
delete[] p;
std::cout << p[0] << "\n"; // UAF

运行后,ASan 会输出:

AddressSanitizer: heap-buffer-overflow
AddressSanitizer: heap-use-after-free

同时显示访问地址、偏移、分配栈和释放栈。


4. 小结与建议

  • CRT Debug Heap:快速定位泄漏,配合 DEBUG_NEW_CrtSetBreakAlloc,适合单次或短小程序分析。
  • Diagnostic Tools:适合交互式堆快照对比,可在调试时精确定位泄漏对象和调用栈。
  • AddressSanitizer:针对越界和 Use-after-free,非常精确,适合调试复杂堆访问错误。

组合使用这三种工具,你可以在 Windows 下 高效发现和修复 C++ 内存安全问题

http://www.dtcms.com/a/490812.html

相关文章:

  • iOS混淆与IPA文件加固深度解析,从反编译风险到苹果应用安全工程实践
  • 眉山建设中等职业技术学校 网站公司网页制作费用大概要多少钱?
  • 张店网站制作首选专家计算机大专生的出路
  • 万网的网站建设广州互联网公司集中在哪个区
  • 数据安全系列7:常用的非对称算法浅析
  • uniapp微信小程序+vue3基础内容介绍~(含标签、组件生命周期、页面生命周期、条件编译(一码多用)、分包))
  • 微信小程序报错 ubepected character `的style换行问题
  • H5封装打包小程序助手抖音快手微信小程序看广告流量主开源
  • 金华建设局网站做爰片在线看网站
  • 如何做二维码链接网站虚拟空间的网站赚钱吗
  • 营业部绩效考核方案与管理方法
  • 光刻刻蚀工艺控制要点及材料技术进展与限制
  • VPS SSH密钥登录配置指南:告别密码,拥抱安全
  • 注入“侨动力” 锻造“湘非链”
  • 做网站自己申请域名还是建站公司菏泽最好的网站建设公司
  • 网站建设方面书籍温州网站建设案例
  • 【Linux】Linux 零拷贝技术全景解读:从内核到硬件的性能优化之道
  • 微软ML.NET技术详解:从数据科学到生产部署的全栈解决方案
  • 镇江网站搜索引擎优化做外贸雨伞到什么网站
  • 网站收录一般多久沈阳建设学院
  • C++ AI 编程助手
  • 编程之python基础
  • 【系统分析师】写作框架:软件设计模式及其应用
  • leetcode 2598 执行操作后最大MEX
  • GPTBots Multi-Agent架构解析:如何通过多Agent协同实现业务智能化升级
  • 深圳网站建设智能小程序礼品网站如何做
  • 预约洗车小程序
  • 四字母域名建设网站可以吗乐清房产在线网
  • 中后台管理系统导航布局切换的技术原理解析
  • 【Android 、Java】为什么HashMap在JDK8中要将链表转换为红黑树的阈值设为8?这个数字是如何确定的?