不兼容的选项和功能
以下选项和功能不兼容 /fsanitize=address
,应禁用或避免。
-
/RTC
选项与 AddressSanitizer 不兼容,应禁用。 - 增量链接不受支持,应禁用。
- Edit-and-Continue 不受支持,应禁用。
- 协同例程与 AddressSanitizer 不兼容,且可恢复函数不在检测范围内。
- OpenMP 不受支持,应禁用。
- Managed C++ 不受支持,应禁用。
- C++ AMP 不受支持,应禁用。
- 通用 Windows 平台 (UWP) 应用程序不受支持。
- 特殊情况列表文件不受支持。
标准库支持
MSVC 标准库 (STL) 部分使用 AddressSanitizer 并提供其他代码安全检查。 有关详细信息,请参阅 container-overflow 错误。
禁用批注或不支持注释的标准库版本中时,STL 代码中引发的 AddressSanitizer 异常仍会识别实际 bug。 但是,如果启用了批注,并且使用支持它们的标准库版本,则它们更精确。
此示例演示了精准率的缺失和启用注释的好处:
// Compile with: cl /fsanitize=address /Zi
#include <vector>
int main() {
// Create a vector of size 10, but with a capacity of 20.
std::vector<int> v(10);
v.reserve(20);
// In versions prior to 17.2, MSVC ASan does NOT raise an exception here.
// While this is an out-of-bounds write to 'v', MSVC ASan
// ensures the write is within the heap allocation size (20).
// With 17.2 and later, MSVC ASan will raise a 'container-overflow' exception:
// ==18364==ERROR: AddressSanitizer: container-overflow on address 0x1263cb8a0048 at pc 0x7ff6466411ab bp 0x005cf81ef7b0 sp 0x005cf81ef7b8
v[10] = 1;
// Regardless of version, MSVC ASan DOES raise an exception here, as this write
// is out of bounds from the heap allocation.
v[20] = 1;
}
重写运算符 new 和 delete
AddressSanitizer (ASAN) 使用自定义版本的 operator new
和 operator delete
查找分配错误,例如 alloc_dealloc_mismatch
。 使用 /INFERASANLIBS
运行链接器可确保 ASAN 的 new
/delete
替代优先级较低,以便链接器选择其他库中的任何 operator new
或 operator delete
替代,而 ASAN 的自定义版本。 发生这种情况时,ASAN 可能无法捕获依赖于其自定义 operator new
和 operator delete
的某些错误。
MFC 包括自定义 operator new
替代, operator delete
并可能错过错误,例如 alloc_dealloc_mismatch
。
内存使用率
AddressSanitizer 运行时在执行期间不会将内存释放回 OS。 从 OS 的角度来看,看似存在内存泄漏。 这是有意的,以便内存并非全部提前分配。
AddressSanitizer 运行时 DLL 位置
clang_rt.asan*.dll
运行时文件安装在 %VSINSTALLDIR%\VC\Tools\MSVC\<version>\bin\<host-arch>\<target-arch>\
中编译器旁边。 这些位置位于调试会话和 Visual Studio 开发人员命令提示符的路径上。 这些文件绝不会放在 C:\Windows\System32
或 C:\Windows\SysWOW64
中。
自定义属性表支持
Visual Studio 属性管理器窗口允许向项目添加自定义 .props
文件。 即使显示了“启用地址清理器”属性(),但版本仍不支持。<EnableASAN>
这是因为自定义 .props
文件包含在之后 Microsoft.cpp.props
,后者使用 <EnableASAN>
该值设置其他属性。
解决方法是,在项目的根目录中创建一个 Directory.Build.props
文件来定义 <EnableASAN>
属性。 有关详细信息,请参阅自定义 C++ 生成。
线程局部变量
线程局部变量(使用 __declspec(thread)
或声明的 thread_local
全局变量)不受 AddressSanitizer 的保护。 此限制不特定于 Windows 或 Microsoft Visual C++,而是一般限制。
部分清理的可执行文件的问题
如果进程中的所有代码未使用 /fsanitize=address
编译,ASan 可能无法诊断所有内存安全错误。 最常见的示例是使用 ASan 编译 DLL,但加载到包含未使用 ASan 编译的代码的进程中。 在这种情况下,ASan 尝试对 ASan 初始化之前发生的分配进行分类。 重新分配这些分配后,ASan 会尝试拥有并监视内存的生存期。
如果在进程结束之前从进程卸载了使用 ASan 编译的所有 DLL,则由于对截获的函数(例如memcmp
,memcpy
memmove
等)的悬而未决的引用可能会崩溃。 为了获得最佳结果,请使用 编译测试 /fsanitize=address
中的所有模块,或者不要卸载使用 ASan 编译的模块,然后进入该过程。
请向 开发人员社区报告任何 bug。
另请参阅
AddressSanitizer 概述
AddressSanitizer 生成和语言参考
AddressSanitizer 运行时参考
AddressSanitizer 阴影字节
AddressSanitizer 云或分布式测试
AddressSanitizer 调试程序集成
AddressSanitizer 错误示例