I was told by @mmozeiko that Address Sanitizer (ASAN) works on Windows now. I'd tried it a few years ago with no luck, so this was exciting news to hear.
It was a pretty smooth experience, but with a few gotchas I wanted to document.
First, download and run the LLVM installer for Windows: https://llvm.org/builds/
Then download and install the VS extension if you're a Visual Studio 2017 user like I am.
It's now very easy to use Clang to build your existing MSVC projects since there's a cl compatible frontend:
To use the LLVM toolchain from Visual Studio after running the installer above, install the LLVM Compiler Toolchain Visual Studio extension (supports Visual Studio 2017 and later), select a project in Solution Explorer, open its Property Page (Alt+F7 by default), and in the "General" section of "Configuration Properties" change "Platform Toolset" to "llvm". Alternatively, invoke MSBuild with /p:PlatformToolset=llvm to try out the toolchain without modifying the project files.
You're probably going to run into some cl settings that it doesn't accept but you can easily change those. Then it's probably going to swamp you in Clang/GCC specific warnings, so you'll want to disable or clean those up.
Now you're ready to actually compile and run ASAN against your code. This is a little more awkward using the VS flow. Most pages recommend compiling and linking with clang in a single invocation with the -fsanitize=address command line flag. However, the VS flow insists on using lld-link to separately link, and this does not take an -fsanitize=address option. Hence you have to do the following:
- Add -fsanitize=address under Additional Compiler Options in the LLVM page of your VS project properties.
- Add the path C:\Program Files\LLVM\lib\clang\9.0.0\lib\windows\clang_rt.asan-x86_64.lib to your linked libraries.
When you first compile with -fsanitize=address you're probably going to get complaints about compiler/linker settings you weren't getting complaints about previously. E.g. you can't use /debug:fastlink or the debug CRT and a few other things. Just fix those as recommended: use /debug:full and use a non-debug CRT.
OK, moment of truth. You launch the ASAN-compiled program from the VS debugger... and it crashes deep in a memset during initialization for some low-level custom allocator code in AsanInitInternal. However, @mmozeiko points out the issue is that ASAN wants to catch Win32 memory access violations, so the debugger can't be intercepting it. You can disable break-on-exception for memory access violations (0xC0000005) under Debug -> Windows -> Exception Settings. Once you do this, you can launch ASAN-compiled programs from the debugger and everything is fine. However, during normal debugging workflow it's essential to have break-on-exception enabled for memory access violations, so you'll have to remember to toggle this on and off when switching between ASAN and non-ASAN debugging.
Since debug settings are saved to the per-solution .vcxproj.user file, it might make sense to write a simple script that launches devenv with a copy of an existing solution with that break-on-exception setting disabled, and with the changes for -fsanitize=address and linking against the ASAN runtime library applied to the project settings. That is, write a generic devenv-asan script that when launched in a directory makes all the requisite setting changes to a temp copy of the solution-related files in that directory and then launches devenv.exe with it.
The Windows and VS integration for Clang and ASAN is already a pretty smooth experience compared to just a year or two ago. If they removed the above mentioned pain points in the VS integration, it would be damn near perfect. You should be able to just right-click a project in the solution explorer and select 'Compile and run with Address Sanitizer' so that you don't have to mess around with the runtime library path or make temporary stateful changes to the project settings and debug settings.
I got it to work with /MT, could you try that? I think you have to link against a different asan-rt library if you use the DLL CRT, and I didn't try that. If you figure out which one/what to do, write it here and I can incorporate it into the article.