Detect Bugs using Google Sanitizers

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.

References

https://clang.llvm.org/docs/UsersManual.html

https://www.jetbrains.com/help/clion/google-sanitizers.html

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.