Thomas Skardal

Hello, computer.

Find memory errors by using the address sanitizer

May 3, 2018

The address sanitizer (ASAN) is a runtime memory error detector. You compile your code with the sanitizer enabled and run it like normally. If ASAN detects a memory error it will report it to you immediately and then exit. I first got aware of this nice tool when hunting a “use after delete” and asking for help on the CppSlack. I don’t remember the wording exactly, but it was something like “you could try running it with ASAN”. I had no idea what it meant and did some searching.

You should look up the documentation on how to use it, but here’s a simple example:

#include <iostream>
#include <string>
#include <vector>

struct Message {
  std::string content;
};

Message* fetchMessage() {
  Message* m = new Message;
  m->content = "Hello world!";
  delete m;
  return m;
}

int main() {
  auto msg = fetchMessage();
  std::cout << "Content: " << msg->content;
  return 0;
}

This is just a silly example of using something that has been deleted. But running this code through clang with ASAN leaves no doubt about where the error resides.

# compile it with sanitizer
❯ clang++ -fsanitize=address -fno-omit-frame-pointer -g -O1 sanitize_this.cpp
# run it and get ASAN report (I've omitted most of it')
❯ ./a.out 
=================================================================
==6887==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000010 at pc 0x000000517910 bp 0x7ffc4dc057f0 sp 0x7ffc4dc057e8
READ of size 8 at 0x603000000010 thread T0
...
    #3 0x51790f in main /home/thomas/Code/cpp/2018-05-silly-sunday/sanitize_this.cpp:18
...
freed by thread T0 here:
...
    #1 0x51788f in fetchMessage() /home/thomas/Code/cpp/2018-05-silly-sunday/sanitize_this.cpp:12:3
...
previously allocated by thread T0 here:
...
    #1 0x5177f7 in fetchMessage() /home/thomas/Code/cpp/2018-05-silly-sunday/sanitize_this.cpp:10:16
...

Even though -fsanitize=address is the only necessary flag, the other flags make the stacktrace much more interesting. If you use Qt and QMAKE you enable it by adding to CONFIG: CONFIG += sanitizer sanitize_address.

Not surprisingly, running your code with ASAN has a performance penalty, so you don’t want this for your production build. Use it while developing/testing and/or as part of CI. It is also worth noting that both g++ and clang provides ASAN support. If your stacktrace looks weird you probably need to tell the compiler where the symbolizer is located. Do some searching and you’ll figure it out.

Take a look at this video for a nice demonstration: https://www.youtube.com/watch?v=MB6NPkB4YVs