- alloc/dealloc 不匹配以及 new/delete 类型不匹配
- 分配对堆过大
- calloc 溢出与 alloca 溢出
- 双重释放 (double free) 与释放后使用 (use after free)
- 全局变量溢出
- 堆缓冲区溢出
- 对齐值的无效对齐
- memcpy 与 strncat 参数重叠
- 栈缓冲区上溢与下溢
- return 后使用栈以及 scope 结束后使用
- 内存中毒后使用
在编译器中启用 ASan
Address Sanitizer 已集成到 Visual Studio 项目系统、CMake 构建系统和 IDE 中。项目可以通过额外的编译器选项/fsanitize=address 或在 Visual Studio 中设置项目属性来启用 AddressSanitizer:
此选项与所有 x64 优化等级和配置兼容。然而,它与
edit-and-continue、incremental linking 和 /RTC 不兼容,在使用 ASan 编译之前必须禁用这些选项。$(VC_LibraryPath_VC_x64) 值是列表中的最后一项,以防止它被用于其他库,如下所示:
ASan 运行时要求
当游戏在启用 ASan 的情况下构建时,需要在运行时提供一个额外的 DLL,该 DLL 启用相关功能。默认情况下,当在编译器中启用 ASan 时,它会将此 DLL 复制到项目的输出目录中,然后应与可执行文件一起部署到主机上。 如需要,可以在 Visual Studio 的$(VC_ExecutablePath_x64) 目录中手动找到这些 DLL。根据构建版本,XBOX 需要以下两者之一:
运行时调试器支持
在附加调试器的情况下运行启用 ASan 的游戏时,如果发现错误,它会中断进入调试器并显示详细报告,让你能确定错误发生的位置。 但如果你在没有附加调试器的情况下运行(例如在自动化测试框架中),则错误信息会显示在标准输出上,游戏会终止。这可能有所帮助,但你可能需要更多状态信息来找到崩溃的根本原因,这就是 Crash Dump 支持发挥作用的地方。如果你在没有附加调试器的情况下运行,且需要在此时解析符号,则需要将
llvm-symbolizer.exe 文件与游戏 EXE 一起部署。此文件与上文列出的 ASan 运行时 DLL 位于同一位置。运行时 Crash Dump 支持
从 Visual Studio 16.9.8 或 16.10.2 起,可以配置 ASan 以保存包含与错误关联的元数据的崩溃转储文件。Visual Studio 中的调试器可以解析该转储文件中保存的元数据,为崩溃提供更多上下文。你可以按构建配置崩溃转储保存,存储这些二进制产物,然后在 IDE 中通过合适的源索引查看它们。 Crash Dump 文档可在此处找到: Configuring Crash Dumps(Microsoft Docs)。 但上述链接的方案需要设置环境变量,而 XBOX 上不支持此操作,因此实现了另一种方法。要为你的 XBOX title 添加 Crash Dump 支持,只需定义一个回调函数,向 ASan 提供所需的崩溃转储文件名信息即可,下面给出了三个示例。为了遵循 Visual Studio IDE 约定,文件名通常以 .dmp 结尾。
与前一个函数一样,此重写在 XBOX 上是可选的,但如果你希望在没有附加调试器的情况下使用 crash dump 来收集 ASan 信息,则强烈推荐使用。如果你提供了转储文件名但未提供 dumptype 重写,则将无法在 XBOX 上生成有效的崩溃转储。
示例 ASan 代码
以下代码演示了这些函数可以多么容易地添加到现有代码库中,并根据需要进行调整:已知问题
- Visual Studio 2019 (16.11) 的 ASan 与 Game OS 不兼容。
- ASan DLL 与 Game OS 不兼容,17.12 和 17.13 的初始版本会加载失败。此问题已在 17.12.6 和 17.13.3 中修复。
- Visual Studio 2022 中导致 Game OS 启动时崩溃的 ASan 支持回归问题,已在 17.14.29 中修复;Visual Studio 2026 中在 18.4.1 中修复。
- 在 XBOX 上使用调试器运行时,会定期发出以下异常消息,可安全忽略:
