# Google sanitizers

> **TL;DR**
> OS: Linux / Windows 10 with [clang-cl](quick-tutorial-on-configuring-clion-on-windows.html#clang-cl) (AddressSanitizer only) or WSL / macOS (AddressSanitizer, ThreadSanitizer, and UndefinedBehaviorSanitizer)
>
>
>
> Project format: [CMake](quick-cmake-tutorial.html) (full support) / [Makefile](makefiles-support.html) and [compilation database](compilation-database.html) (no output visualization)
>
>
>
> Toolchain: local / [remote](remote-projects-support.html) / [WSL](how-to-use-wsl-development-environment-in-product.html) / [Docker](clion-toolchains-in-docker.html)

[Sanitizers](https://github.com/google/sanitizers) are open-source tools for dynamic code analysis designed by Google. CLion integrates with the following Sanitizers:

* AddressSanitizer (ASan)

* LeakSanitizer (LSan)

* ThreadSanitizer (TSan)

* UndefinedBehaviorSanitizer (UBSsan)

* MemorySanitizer (MSan)

> **Tip:**
> Useful links: [Official documentation](https://github.com/google/sanitizers), [Sanitizers in Clang](http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation), [Sanitizers among Program Instrumentation Options in GCC](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html).

Sanitizers are implemented in Clang starting 3.1 and GCC starting 4.8. All the sanitizers are available on Linux x86_64 machines. You can use AddressSanitizer on Windows 10 with [clang-cl](quick-tutorial-on-configuring-clion-on-windows.html#clang-cl) under the MSVC toolchain. For macOS, the supported sanitizers are AddressSanitizer, ThreadSanitizer, and UndefinedBehaviorSanitizer.

As Sanitizers are based on compiler instrumentation, you need to rebuild your project in order to start using these tools.

## Configure Sanitizers

Procedure: Specify compiler flags

* Adjust the following template line and add it to your `CMakeLists.txt`:

```CMAKE
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=[sanitizer_name] [additional_options] [-g] [-OX]")
```

> **Note:**
> Use `CMAKE_C_FLAGS` instead of `CMAKE_CXX_FLAGS` for C projects.

For `[sanitizer_name]` use one of the following:

* address for AddressSanitizer

* leak for LeakSanitizer

* thread for ThreadSanitizer

* undefined for UndefinedBehaviorSanitizer (other options are also available, refer to the [UBSan section](#UbSanChapter))

* memory for MemorySanitizer

`[Additional_flags]` are other compilation flags, such as `-fno-omit-frame-pointer`, `fsanitize-recover/fno-sanitize-recover`, `-fsanitize-blacklist`, etc.

Use `[-g]` to have file names and line numbers included in warning messages.

Add optimization level `[-OX]` to get reasonable performance (see recommendations in the particular Sanitizer documentation).

Procedure: Sanitizers for non-CMake projects

* If you are working with a [Makefile project](makefiles-support.html) or a [compilation database](compilation-database.html) project with [custom build targets](custom-build-targets.html), make sure to specify linker flags along with the compiler flags. For example, in the case of a Makefile and [AddressSanitizer](#AsanChapter):

![Sanitizer flags in a Makefile](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_makefile.png)

> **Note:**
> Sanitizers' output [visualization](#SanitizersSettings) is available for CMake projects only. For Makefiles and compilation databases, the output is logged to console in plain text.

Procedure: Adjust the Sanitizers settings

* Go to `Settings | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers` and set up the following:

![Sanitizers settings](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_settings.png)

* Run-time flags In this section, specify the run-time options for each Sanitizer. You can do that manually or by clicking the Import flags from existing environment variables button (this button becomes available if the variables `ASAN/MSAN/LSAN/TSAN_OPTIONS` are presented). See [Sanitizer Common flags](https://github.com/google/sanitizers/wiki/SanitizerCommonFlags).

* Use visual representation for Sanitizer's output Set this checkbox to have a tree-view output with the Preview Editor and Frame Information: ![CLion Sanitizers visual output](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_visualoutput.png) For the visualized output to be available, switch to Clang at least 3.8.0 or GCC at least 5.0.0. For more information about changing a compiler in CLion, refer to this [instruction](how-to-switch-compilers-in-clion.html). The Sanitizers view allows jumping back to source code and also copying the warning data to clipboard: ![Sanitizers view actions](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_view_actions.png) When the visual representation checkbox is cleared, or the compiler does not fit the requirements, the sanitizers output is presented in plain text: ![CLion Sanitizers plain output](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_freetext.png)

Procedure: Provide the path to llvm-symbolizer

To let Sanitizers convert addresses into source code locations and make stack-traces easy to understand, ensure that the `PATH` or `*SAN_SYMBOLIZER_PATH` environment variable contains the location of [llvm-symbolizer](https://llvm.org/docs/CommandGuide/llvm-symbolizer.html).

Use one of the options:

* Add the path to llvm-symbolizer directory (for example, `/usr/bin/`) to system PATH.

* In the [Environment variables](run-debug-configuration.html#envvars-progargs) field of the run/debug configuration, add `*SAN_SYMBOLIZER_PATH` pointing to the particular binary (like `/usr/bin/llvm-symbolizer`).

In case of using Clang compiler, you will get a notification from CLion if none of the `PATH` or `*SAN_SYMBOLIZER_PATH` variables points to llvm-symbolizer:

![cl_sanitizer_symbolizerwarning.png](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizer_symbolizerwarning.png)

## AddressSanitizer

[AddressSanitizer (ASan)](https://github.com/google/sanitizers/wiki/AddressSanitizer) is a memory corruption detector, capable of finding the following types of bugs:

* Heap-, stack-, and global buffer overflow

* Use-after-free (dangling pointer dereference)

* Use-after-scope `-fsanitize-address-use-after-scope`

* Use-after-return (pass `detect_stack_use_after_return=1` to `ASAN_OPTIONS`)

* Double free, invalid free

* Initialization order bugs

> **Tip:**
> ASan in details: [FAQ](https://github.com/google/sanitizers/wiki/AddressSanitizer#faq), [List of flags](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags), [How to use ASan with GDB](https://github.com/google/sanitizers/wiki/AddressSanitizerAndDebugger), [Turning off ASan instrumentation](https://github.com/google/sanitizers/wiki/AddressSanitizer#turning-off-instrumentation), [ASan Algorithm](https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm), [ASan in Clang](http://clang.llvm.org/docs/AddressSanitizer.html).

As an example, consider the following code fragment:

```CPLUSPLUS
int global_array[100] = {-1};

int main(int argc, char **argv) {
    return global_array[argc + 100];  // global buffer overflow
}
```

When built with `-fsanitize=address -fno-omit-frame-pointer -O1` flags, this program will exit with a non-zero code due to the global buffer overflow detected by AddressSanitizer:

![AddressSanitizer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_asan.png)

Note that ASan halts on the first detected error. To change this behavior and make ASan continue running after reporting the first error, add `-fsanitize-recover=address` to compiler flags and `halt_on_error=false` to `ASAN_OPTIONS`.

Procedure: Configure AddressSanitizer on Windows

On Windows, you can work with AddressSanitizer under the [MSVC toolchain](quick-tutorial-on-configuring-clion-on-windows.html#MSVC) using the [clang-cl](quick-tutorial-on-configuring-clion-on-windows.html#clang-cl) compiler.

1. Run the Visual Studio Installer and make sure to install the C++ AddressSanitizer component. You can find it under the Desktop Development with C++ node:

![Selecting AddressSanitizer in Visual Studio Installer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_msvc_installer.png)

2. In CLion, go to `Settings | Build, Execution, Deployment | Toolchain` and create a new Visual Studio toolchain or edit an existing one.

* Set Architecture to x86_amd64.

* Set the paths to clang-cl in the C Compiler and C++ Compiler fields. You can use clang-cl from the [LLVM distribution](https://releases.llvm.org/download.html) or from the Visual Studio tools. In the latter case, the path will be, for example, `C:\Program Files(x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\bin\clang-cl.exe`.

![MSVC toolchain with clang-cl](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_msvc_toolchain.png)

3. In your `CMakeLists.txt`, add the following lines after the `add_executable` command (replace `exec` with the name of your executable):

```CMAKE
target_compile_options(exec PRIVATE -fsanitize=address)
target_link_directories(exec PRIVATE "$ENV{ProgramFiles\(x86\)}/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/lib/clang/10.0.0/lib/windows")
target_link_libraries(exec PRIVATE clang_rt.asan_dynamic-x86_64 clang_rt.asan_dynamic_runtime_thunk-x86_64)
target_link_options(exec PRIVATE /wholearchive:clang_rt.asan_dynamic_runtime_thunk-x86_64.lib)
```

Adjust the `ProgramFiles\(x86\)}/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/lib/clang/10.0.0/lib/windows` path if required. This directory contains the libraries required for AddressSanitizer.

4. Go to `Settings | Build, Execution, Deployment | CMake`, create a Release [profile](cmake-profile.html), and set it as the default (move it to the top of the profile list):

![Release CMake profile](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_release_profile.png)

5. Try to load and build the project. In case of linker errors, copy all the files from `ProgramFiles\(x86\)}/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/lib/clang/10.0.0/lib/windows` into the `cmake-build-release` folder.

## LeakSanitizer

[LeakSanitizer (LSan)](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer) is a memory leak detector. In a stand-alone mode, this Sanitizer is a run-time tool that does not require compiler instrumentation. However, LSan is also integrated into AddressSanitizer, so you can combine them to get both memory errors and leak detection.

> **Tip:**
> Learn more about LSan: [Design Document](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerDesignDocument) , [LSan in Clang](https://clang.llvm.org/docs/LeakSanitizer.html).

To enable LeakSanitizer as a part of AddressSanitizer, pass `detect_leaks=1` to the `ASAN_OPTIONS` variable. To run ASan-instrumented program without leak detection, set `detect_leaks=0`.

To run LSan only (and avoid the ASan's slowdown), use `-fsanitize=leak` instead of `-fsanitize=address`.

The following code leads to a memory leak due to no-deleting of a heap-allocated object:

```CPLUSPLUS
int main(){
    int *x = new int(10);
    return 0;
}
```

LSan detects and reports the problem:

![LeakSanitizer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_lsan.png)

> **Note:**
> LeakSanitizer doesn't work under ptrace, so it can't be used in debug mode.

## ThreadSanitizer

[ThreadSanitizer (TSan)](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual) is a data race detector. Data races occur when multiple threads access the same memory without synchronization and at least one access is a write.

> **Tip:**
> TSan in depth:
>
> * [Dynamic Race Detection with LLVM Compiler \[pdf\]](https://static.googleusercontent.com/media/research.google.com/ru//pubs/archive/37278.pdf)
>
> * [Description of some most popular data races](https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces)
>
> * [TSan detectable bugs](https://github.com/google/sanitizers/wiki/ThreadSanitizerDetectableBugs)
>
> * [TSan flags](https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags)
>
> * [TSan in Clang](http://clang.llvm.org/docs/ThreadSanitizer.html)

Take a look at the following code that produces data races:

```CPLUSPLUS
#include <pthread.h>
#include <stdio.h>

int Global;

void *Thread1(void *x) {
    Global++;
    return NULL;
}

void *Thread2(void *x) {
    Global--;
    return NULL;
}

int main() {
    pthread_t t[2];
    pthread_create(&t[0], NULL, Thread1, NULL);
    pthread_create(&t[1], NULL, Thread2, NULL);
    pthread_join(t[0], NULL);
    pthread_join(t[1], NULL);
}
```

When you run this program compiled with `-fsanitize=thread -fPIE -pie -g`, TSan prints a report of a data race. For more information about the output format, refer to [ThreadSanitizerReportFormat](https://github.com/google/sanitizers/wiki/ThreadSanitizerReportFormat).

![ThreadSanitizer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_tsan.png)

## UndefinedBehaviourSanitizer

[UndefinedBehaviorSanitizer (UBSan)](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) is a runtime checker for undefined behavior, which is a result of any operation with unspecified semantics, such as dividing by zero, null pointer dereference, or usage of an uninitialized non-static variable.

UBSan catches various kinds of undefined behavior, see the full list at [clang.llvm.org](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#ubsan-checks). You can turn the checks on one by one, or use flags for check groups `-fsanitize=undefined`, `-fsanitize=integer`, and `-fsanitize=nullability`.

Code below illustrates the situation of an undefined result of a shift operation:

```CPLUSPLUS
int main() {
    int i = 2048;
    i <<= 28;
    return 0;
}
```

If you compile this code with the `-fsanitize=undefined` flag (alternatively, use `-fsanitize=shift`) and launch, the program will finish successfully despite of the UBSan warning:

![UndefinedBehaviorSanitizer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizer_ubsan.png)

To make a program exit due to UBSan's diagnostics, use the `-fno-sanitize-recover` option.

## MemorySanitizer

[MemorySanitizer (MSan)](https://github.com/google/sanitizers/wiki/MemorySanitizer) is a detector of uninitialized memory reads. This Sanitizer finds the cases when stack- or heap-allocated memory is read before it is written. MSan is also capable of tracking uninitialized bits in a bitfield.

> **Note:**
> MSan is only available in Clang for Linux x86_64 targets.

MSan can track back the origins of an uninitialized value to where it was created and report this information. Pass the `-fsanitize-memory-track-origins` flag to enable this functionality.

To efficiently use MSan, compile your program with `-fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g`, add `-fno-optimize-sibling-calls` and `-O1` or later.

Find the example of code with an uninitialized read and the corresponding MSan output below:

```CPLUSPLUS
int main(int argc, char** argv) {
    int* a = new int[10];
    a[5] = 0;
    if (a[argc])
        std::cout << a[3];
    return 0;
}
```

![MemorySanitizer](https://resources.jetbrains.com/help/img/idea/2026.2/cl_sanitizers_msan.png)

## See also

