带MSVC的Windows的AddressSanitizer(ASan)

这篇文章最后一次更新是在2021年3月24日,提供了有关ASan支持的最新信息。

null

注: 此功能现在已普遍可用。首先,看看官方网站 带MSVC的Windows地址消毒器 文档。自从这篇博文发表以来,我们的经验有了许多改进,我们的文档中有最新的信息。

我们很高兴宣布 消毒液(ASan) 支持MSVC工具集。ASan是一个快速的内存错误检测器,它可以发现运行时内存问题,比如空闲后的使用,并执行越界检查。 对消毒剂的支持 这是我们比较流行的建议之一 开发者社区 ,我们现在可以说,除了我们的 对Linux项目的现有支持 .

在微软,我们相信开发人员应该能够使用他们选择的工具,我们很高兴与LLVM团队合作,将他们的更多工具引入visualstudio。在过去,我们还集成了 叮当声格式 最近,叮当作响。MSVC对ASan的支持在我们的第二个版本中提供 Visual Studio 2019版本16.4预览版 .

为了把ASan带到Windows和MSVC,我们做了 以下更改:

  • ASan运行时已更新为更好地针对Windows二进制文件
  • MSVC编译器现在可以用ASan来处理二进制文件
  • CMake和MSBuild集成已更新,以支持启用ASan
  • visualstudio调试器现在可以检测Windows二进制文件中的ASan错误
  • 可以从VisualStudio安装程序安装ASAN,用于C++桌面工作负载

在visualstudio中调试ASan插入指令的二进制文件时,遇到问题时将显示IDE异常帮助程序,并且程序执行将停止。您还可以在输出窗口中查看详细的ASan日志信息。

ASan Exception in Visual Studio

安装ASan对Windows的支持

对于新安装,ASAN默认包含在C++桌面工作负载中。但是,如果您是从旧版本的Visual Studio 2019升级,则需要在升级后在安装程序中启用ASan支持:

Visual Studio Installer with ASan checkbox

你可以点击 修改 在现有的visualstudio安装上从visualstudio安装程序转到上面的屏幕。

注意:如果在新更新上运行Visual Studio,但尚未安装ASan,则在运行代码时将出现以下错误:

LNK 1356–找不到库’clangu rt.asanu dynamic-i386.lib’

为Windows MSBuild项目启用ASan

通过在中的项目上单击鼠标右键,可以为MSBuild项目启用ASan 解决方案管理器 ,选择 属性 ,在C/C+++>导航下,改变 启用地址消毒剂(实验) 选项。同样的方法也可以用于为msbuildlinux项目启用ASan。

Enabling ASan in the MSBuild project properties

注: 目前,这只适用于x86发行版目标,不过我们将在未来扩展到更多的体系结构。

为Windows CMake项目启用ASan

要为针对Windows的CMake项目启用ASan,请执行以下操作:

  1. 打开IDE顶部的Configurations下拉列表并单击 管理配置 . 这将打开保存在CMakeSettings.json文件中的CMake项目设置UI。
  2. 单击 编辑JSON UI中的链接。这将把视图切换到raw.json。
  3. x86版本 配置时,添加以下属性: “AddressSanitizeEnabled”:真

您可能会在上面的线下看到一条绿色曲线,并显示以下警告: 架构不允许使用属性名 . 这是一个很快就会被修复的bug–该属性实际上可以工作。

以下是更改后CMakeSettings.json文件的相关部分的图像:

Enabling ASan in the CMakeSettings.json file

在将来的更新中,我们将进一步简化在CMake项目中启用ASan的过程。

对ASan运行时的贡献

为了实现一个伟大的Windows体验,我们决定为 LLVM编译器rt项目 并在我们的ASan实现中重用它们的运行时。我们对ASan项目的贡献包括错误修复和改进的拦截 中分配内存 , RtlAllocateHeap公司 , 球形 ,和 局部分配 ,以及相应的 免费的 , 重新分配 ,和 大小 功能。任何人都可以通过将以下内容添加到 ASANU选项 Windows上Clang或MSVC的环境变量:

set ASAN_OPTIONS= windows_hook_rtl_allocators=true

其他选项 可以在上面一行的末尾加上冒号。

更改MSVC以启用ASan

为了启用ASan,修改了c1.dll和c2.dll,以便在编译时向程序添加插装。对于32位地址空间,大约分配200 MB内存来表示(或“阴影”)整个地址空间。进行分配时,将修改阴影内存,以表示分配现在对访问有效。当分配被释放或超出作用域时,将修改卷影内存以显示此分配不再有效。对具有潜在危险的内存访问,将对照其在阴影内存中的条目进行检查,以验证该内存当时是否可以安全访问。冲突作为stderr或visualstudio中的异常窗口的输出报告给用户。在进行访问之前,检查阴影内存中的分配数据。AddressSanitizer算法使错误报告能够准确地显示问题发生的位置和出错的地方。

这意味着用MSVC+ASan编译的程序也有相应的clang_rt.ASan库链接到它们的目标。每个库都有一个特定的用例,如果您的程序很复杂,链接可能会很复杂。

从控制台用ASan编译

如果您使用的是Visual Studio版本16.9 Preview 3或更高版本,则 fsanitize=address 编译器标志被指定,ASan库被自动链接(对于控制台和IDE构建)。

对于控制台编译,如果启用 Visual Studio版本16.9 Preview 2或更早版本 ,则必须手动链接ASan库。以下是x86目标所需的库:

  • 叮当声.asan-i386.lib –与MT/CRT兼容的静态运行时。
  • 叮当声.asanu cxx-i386.lib -静态运行时组件,增加了对new和delete的支持,也与/MT-CRT兼容。
  • 叮当声.asanu dynamic-i386.lib –动态导入库,与MD/CRT兼容。
  • 叮当声.asanu dynamic-i386.dll –动态运行时DLL,与/MD兼容。
  • 叮当声u rt.asan u动态u运行时u thunk-i386.lib –用于手动导入和截取某些/MD CRT函数的动态库。
  • 叮当声.asanu dllu thunk-i386.lib –导入库,允许ASAN插入指令的DLL使用链接到主可执行文件的静态ASAN库。与MT/CRT兼容。

一旦选择了要使用的正确ASan运行时,就应该添加 /wholearchive: 并将相应的库添加到可执行文件中。clang_rt.asan_dynamic_i386.dll未安装到System32中,因此运行时应确保它在环境的搜索路径中可用。

一些附加说明:

  • 编译单个静态EXE时: 链接静态运行时( asan-i386.lib) 以及cxx库(如果需要)。
  • 使用/MT运行时编译EXE时,将使用插入指令的DLL: EXE需要 asan-i386.lib文件 链接和DLL需要 叮当声.asanu dllu thunk-i386.lib . 这允许dll使用链接到主可执行文件的运行时,并避免阴影内存冲突问题。
  • 使用/MD动态运行时编译时: 所有带指令插入的EXE和DLL都应与 asanèu动态-i386.lib 叮当声u rt.asan u动态u运行时u thunk-i386.lib . 在运行时,这些库将引用 叮当声.asanu dynamic-i386.dll 在运行时共享。

ASan运行库在运行时修补内存管理函数,并将执行重定向到管理卷影内存的ASan包装函数。如果运行时环境与所编写的库所期望的不同,这可能是不稳定的。请通过下面的反馈渠道提交在使用ASan时遇到的任何编译或运行时错误!

注: 使用非ASan指令化EXE加载ASan指令化dll,而不链接clangu-rt.ASan-u dynamic和clangu-rt.ASan-u dynamic­_运行时u thunk库将导致ASan报告为假阳性。这是由于在程序初始化和加载ASan插入指令的DLL之间创建了分配。在此窗口期间创建的任何分配在传递到新截获的CRT函数时都将导致错误的错误报告。如果将动态导入库链接到主可执行文件中,则可以避免这些误报;因为以这种方式链接动态运行时库允许拦截器在适当的时间初始化。一定要使用/wholearchive链接器标志来确保asan的init例程没有在主exe中被优化掉。

给我们反馈!

您的反馈对于我们提供在VisualStudio中运行ASan的最佳体验至关重要。我们希望您能试用最新的预览版 Visual Studio 2019版本16.4 并让我们知道它是如何为您工作,无论是在下面的评论或 通过电子邮件 . 如果您在体验中遇到问题或有改进建议,请 报告问题 或者通过 开发者社区 . 你也可以在Twitter上找到我们 @视觉 .

© 版权声明
THE END
喜欢就支持一下吧,技术咨询可以联系QQ407933975
点赞0 分享