您当前的位置:首页 > 计算机 > 软件应用 > 开发工具(IDE)

Visual Studio 中使用 AddressSanitizer 指南

时间:09-02来源:作者:点击数:
CDSY,CDSY.XYZ

Visual Studio 中使用 AddressSanitizer 指南

基于 Microsoft Visual Studio 2022,支持 MSVC 和 Clang 编译器链,本文详细说明如何在 VS 中配置和使用 AddressSanitizer,用于检测内存误用,如消息释放后访问、超界读写等类型错误。


一、ASan 是什么?

AddressSanitizer (ASan) 是一个轻量级的内存检测器,用于在运行时检测:

  • 访问已释放的内存 (Use-after-free)
  • 堆/栈/全局超界读写 (Buffer overflow)
  • 未初始化内存访问
  • Double free / 内存泄漏

ASan 实际上是编译器打表 + 扩展运行时加载组成,这需要对应的编译器支持。


二、安装 AddressSanitizer 支持

重点:VS2022 配置项
  1. 打开 Visual Studio Installer
  2. 点击“修改”已安装的 VS 版本
  3. 搜索 AddressSanitizer,勾选 C++ AddressSanitize 组件
  4. (选填) 勾选 Clang Toolchain:
    • “适用于 Windows 的 C++ Clang 编译器”
    • “LLVM(clang-cl) 工具集”

如果未安装该组件,MSVC 无法使用 /fsanitize=address 选项!

在这里插入图片描述
在这里插入图片描述

三、Visual Studio 中的两种工具链

在 Visual Studio 中可以选择使用:

工具链 描述
MSVC(默认) 微软自研编译器,性能好,兼容性强
Clang/LLVM Clang 编译器,支持更强的诊断能力和 ASan

若希望启用 AddressSanitizer,推荐使用 Clang 工具链(clang-cl)


四、MSVC 编译器下启用 ASan

  1. 使用 MSVC (Visual Studio 默认)
  2. 项目属性中设置:
(注意配置 Debug / x64)
  • C/C++ -> 调试信息格式 设置为 程序数据库 (/Zi)
  • C/C++ -> 全局选项 设置:
    • 启用地址清理系统 : 是 (/fsanitize=address)
    • 优化 : 已禁用 (/Od)
  • 链接器 -> 生成调试信息 : /DEBUG
在这里插入图片描述

❗备注:实际上现在已经支持 x64 和 Release 版本,所以调试信息、优化等默认即可。

示例代码
#include <iostream>

int main()
{
    int* p = new int(123);
	std::cout << *p << std::endl;   // 正常访问内存
    delete p;                       // 释放内存
    std::cout << *p << std::endl;   // 悬空指针访问,应该触发 ASan 报错
    std::cin.get();                 // 等待输入,保持控制台窗口
    return 0;
}

运行后输出:

在这里插入图片描述
运行时:
  • 不要用 F5 (调试)
  • 请使用 Ctrl + F5 (开始执行,不调试)

注意:千万不要使用调试(F5)。


五、MFC / 图形界面程序中查看 AddressSanitizer 输出

AddressSanitizer(ASan)默认将检测信息通过控制台(标准输出)打印出来。但对于 MFC、Qt 等图形界面程序,Visual Studio 默认构建为 “Windows 子系统”,是不显示控制台窗口的,导致你可能根本看不到报错信息。

✅ 解决方式一:手动打开控制台窗口

可以在程序入口初始化时调用以下代码,手动打开一个控制台窗口,接收 ASan 的输出:

#include <windows.h>
#include <iostream>

void EnableConsole()
{
    AllocConsole();
    FILE* pCout;
    freopen_s(&pCout, "CONOUT$", "w", stdout);
    freopen_s(&pCout, "CONOUT$", "w", stderr);
    freopen_s(&pCout, "CONIN$", "r", stdin);
    std::ios::sync_with_stdio();
    std::cout.clear();
    std::cerr.clear();
    std::cin.clear();
}

然后在 InitInstance()(MFC)或 main() 中调用:

EnableConsole();
✅ 解决方式二:在命令行中运行 GUI 程序

你也可以通过命令行(如 PowerShell、CMD)进入程序目录,直接运行程序:

cd D:\WorkCode\MyApp\bin\x64\Debug
MyApp.exe

控制台会输出 AddressSanitizer 的详细错误信息(含堆栈地址)。


六、Clang Toolchain 注意事项

VS 支持 Clang-cl 实现简单 ASan 分析,但有些限制:

  • 需要自己配置 ASAN_SYMBOLIZER_PATH
  • Clang 进程运行时无法读取原始 PDB 路径
  • 无法完整显示 free 时的堆栈调用栏

现阶段下,建议先使用 MSVC + ASan 进行调试


七、数据解码 symbolizer 应用

如果看到:

WARNING: Failed to use and restart external symbolizer!
AddressSanitizer can not provide additional info.

说明未连接到 symbolizer,需要设置环境变量:

ASAN_SYMBOLIZER_PATH="C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64\bin\llvm-symbolizer.exe"

注意是 exe 路径,且 VS 需要重新打开以便环境变量生效

可选配置:

ASAN_OPTIONS=fast_unwind_on_malloc=0:verbosity=1

八、Clang vs MSVC:使用体验差异

对比项 MSVC 工具链 Clang 工具链
是否支持 AddressSanitizer ❌ 部分支持(需其他手段) ✅ 原生支持
调用栈符号是否完整 ❌(需配合符号服务器) ✅(配合 llvm-symbolizer)
是否支持释放位置追踪 ✅(前提是配置正确)
调试体验 VS 原生调试器佳 调试信息略难查看

注意:当前 Visual Studio + Clang-cl 工具链下的 ASan 功能仍有局限,例如释放堆栈无法完整显示(除非使用原生 clang++ 工具链和 CMake 工程)。


九、Clang 工具链支持现状

虽然 ASan 支持 Clang,但在 Windows 上使用 LLVM (clang-cl) 工具集时,当前版本的 Visual Studio 中 并不能很好地兼容 symbolizer 输出

当前问题:
  • 报错时能捕捉越界或悬空指针问题,但栈信息无法正常符号化。
  • ASAN_SYMBOLIZER_PATH 设置无效或无触发。
原因:

MSVC 的 asan_runtime 模块在内部链接时处理了符号信息传递,而 clang-cl 的 runtime 在 Windows 下并未完整实现符号解析。

建议:
  • 如果追求准确堆栈,建议当前仍使用 MSVC 工具集进行分析。
  • 可关注 LLVM for Windows 后续进展,或在 WSL/Linux 环境下使用 Clang + ASan。

十、官方参考文档


小结

目标 建议设置
快速检测内存误用 MSVC + AddressSanitizer
需要释放类调用堆栈 原生 clang++ + CMake + symbolizer
文件细节 symbol 设置 ASAN_SYMBOLIZER_PATH
CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐