Google Sanitizers are a set of dynamic code analysis tools to detect common bugs in your code, including
- Thread Sanitizer: detect data race, thread leak, deadlock
- Address Sanitizer: detect buffer overflow, dangling pointer dereference
- Leak Sanitizer: part of Address Sanitizer, detect memory leak
- Undefined Behavior Sanitizer: detect integer overflow, float-number overflow
- Memory Sanitizer: detect of uninitialized memory reads
Preparation
For Windows users, install gcc with MinGW, or install Clang
For Mac users, install Clang using `xcode-select –install`
For Linux users, make sure you have gcc installed.
Open CLion and make sure that the run button is clickable with toolchains configured correctly.
Run Program with Sanitizer
To run a program with sanitizer, we need a special flag -fsanitize
to the compiler. Common options include: -fsanitize=address
, -fsanitize=thread
, -fsanitize=memory
, -fsanitize=undefined
, -fsanitize=leak
. A full list of options can be found here.
Note that it is not possible to combine more than one of the -fsanitize=address
, -fsanitize=thread
, and -fsanitize=memory
checkers in the same program, so you may need to toggle the options multiple times for a comprehensive checking.
For testing, let’s add the following line to the CMakeLists.txt file:
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
When you run the code, you should be able to see a sanitizer tab next to the console.
Thread Sanitizer Example
Here is a poorly-written multithreading program:
int counter = 0; pthread_mutex_t lock; void *inc() { pthread_mutex_lock(&lock); // lock not initiazlied counter++; // thread contention pthread_mutex_unlock(&lock); return NULL; } void thread_bugs() { pthread_t tid; for (int i = 0; i < 2; ++i) pthread_create(&tid, NULL, inc, NULL); printf("%d", counter); // print the result before join pthread_join(tid, NULL); // the first thread is not joined }
Add the following line to the CMakeLists.txt to enable the Thread Sanitizer
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
When the program is executing, the sanitizer will generate a report for thread-related bugs. Be aware that your program might run significantly slower with sanitizers enabled.
The sanitizer noticed that two threads are reading/writing to the same memory location at the line counter++;
, since we the locked is used before initialized.
There is also a data race between counter++ and the print statement since the main thread did not wait for one of the child threads.
Finally, there is a thread leak by the same reason above.
Address Sanitizer Example
To enable the Address Sanitizer, you need to add the following line to the CMakeLists.txt
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
It helps you detect heap overflow, which may happen when you incorrectly calculated the size.
Here is an example of overflowing a stack-allocated array
The Address Sanitizer also checks for using freed pointers. Note that it shows you where is memory is allocated and freed.
Here is a silly example of freeing the same memory twice, but it will be less noticeable when different pointers are pointing to the same heap location.