No more leaks with sanitize flags in gcc and clang

If you are programming in C and C++, you are probably wasting at least some of your time hunting down memory problems. Maybe you allocated memory and forgot to free it later.

A whole industry of tools has been built to help us trace and solve these problems. On Linux and MacOS, the state-of-the-art has been valgrind. Build your code as usual, then run it while under valgrind and memory problems should be identified.

Tools are nice but a separate check breaks your workflow. If you are using recent versions of the GCC and clang compilers, there is a better option: sanitize flags.

Suppose you have the following C program:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
   char * buffer = malloc(1024);
   sprintf(buffer, "%d", argc);
   printf("%s",buffer);
}

Save this file as s.c. The program should simply print out how many arguments were entered on the command line. Notice the call to malloc that allocates a kilobyte of memory. There is no accompanying call to free and so the kilobyte of memory is “lost” and only recovered when the program ends.

Let us compile the program with the appropriate sanitize flags (-fsanitize=address -fno-omit-frame-pointer):

gcc -ggdb -o s s.c -fsanitize=address -fno-omit-frame-pointer

When you run the program, you get the following:

$ ./s

=================================================================
==3911==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1024 byte(s) in 1 object(s) allocated from:
    #0 0x7f55516b644a in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x9444a)
    #1 0x40084e in main /home/dlemire/tmp/s.c:6
    #2 0x7f555127eec4 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)

SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).

Notice how it narrows down to the line of code where the memory leak came from?

It is even nicer: the return value of the command will be non-zero meaning that if this code was run as part of software testing, you could automagically flag the code as being buggy.

While you are at it, you can add other sanitize flags such as -fsanitize=undefined to your code. The undefined sanitizer will warn you if you are relying on undefined behavior as per the C or C++ specifications.

These flags represent significant steps forward for people programming in C or C++ with gcc or clang. They make it a lot more likely that your code will be reliable.

Really, if you are using gcc or clang and you are not using these flags, you are not being serious.

9 thoughts on “No more leaks with sanitize flags in gcc and clang”

    1. The caveat is that they are only available on recent versions of the compilers but I stress that they are no longer “experimental” or “bleeding edge”. They work out-of-the-box without fiddling, without unnecessary bugs.

      I don’t know whether they work for all targets, but I suspect that they must.

  1. Will this functionality find memory allocations in more complex scenarios? Like when you allocate mem at some point, pass it around the app and the forget about deleting?

    BTW: Is there something similar for MSVC? You can use clang with VS 2015… so maybe that way you can take advantage of it somehow?

    1. Will this functionality find memory allocations in more complex scenarios? Like when you allocate mem at some point, pass it around the app and the forget about deleting?

      Of course. Though it will only tell you where the memory was allocated, not where it should have been freed.

      BTW: Is there something similar for MSVC? You can use clang with VS 2015… so maybe that way you can take advantage of it somehow?

      I don’t think you can “use clang with VS 2015”. As far as I can tell, Microsoft only allows you to use the clang parser. These sanitizers have to do with the generated code, not merely the parser. So it is different.

      1. aaa… right, so the sanitizers cannot be invoked from VS and thus you cannot use this feature.
        I hope VS will create something similar soon…

  2. It’s a bad idea to run with these sanitizers outside of testing environments though, definitely not in production.

    As far as I’m aware there’s been no effort to ensure the security of the sanitizer runtimes themselves, so even if they protect against memory bugs in application code, there are pretty huge security holes in the runtimes. See: http://seclists.org/oss-sec/2016/q1/363

    They’re great for testing though (we run address-sanitizer builds as part of our regular testing).

    1. It’s a bad idea to run with these sanitizers outside of testing environments (…)

      Though I was maybe not sufficiently clear in my blog post, I meant to refer to these sanitizers as superior alternatives (or complements) to other testing and debugging tools like valgrind.

      However, since they can help produce better code, I think that they may end up generating more secure software.

Leave a Reply

Your email address will not be published. Required fields are marked *