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,undefined -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=thread -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.
References
https://clang.llvm.org/docs/UsersManual.html
https://www.jetbrains.com/help/clion/google-sanitizers.html