5

The GCC and Clang compilers both have support for LeakSanitizer which helps finding memory leaks in C programs. Sometimes a memory leak is unavoidable (because it is being tested in a test suite for example).

Such memory can be annotated using the Leak Sanitizer interface:

#include <sanitizer/lsan_interface.h>

void *p = create_new_object();
__lsan_ignore_object(p);

This will however break on compilers that do not support LSan. In Address Sanitizer, this construct can be used to detect the availablity of ASAN:

/* __has_feature(address_sanitizer) is used later for Clang, this is for
 * compatibility with other compilers (such as GCC and MSVC) */
#ifndef __has_feature
#   define __has_feature(x) 0
#endif

#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
    /* ASAN-aware code here. */
#endif

There is no __has_feature(leak_sanitizer) to detect just the existence of LSan in Clang and neither does __SANITIZE_LEAKS__ exist for GCC. How can I detect ASAN availability anyway? Note that LSan can be enabled independently of AddressSanitizer and ThreadSanitizer.

Lekensteyn
  • 64,486
  • 22
  • 159
  • 192

2 Answers2

3

As the compiler does not set a preprocessor define for itself one have to do that for himself.

One compile with -fsanitize=leak -DMYLEAKSAN=1 with LeakSanitizer or without LeakSanitizer one compile with -DMYLEAKSAN=0. If one does forget to define MYLEAKSAN the compiler is halted.

#ifndef MYLEAKSAN
#   error: MYLEAKSAN must be either 0 or 1
#endif
#include <stdio.h>
#include <stdlib.h>
#if MYLEAKSAN
#   include <sanitizer/lsan_interface.h>
#endif

int main(void)
{
    void *p = malloc(5);
#if MYLEAKSAN
    __lsan_ignore_object(p);
#endif
}
4566976
  • 2,419
  • 1
  • 10
  • 14
  • 1
    Or similarly define my_leaksan_ignore_object(arg) to expand to nothing or the real call. This is less ugly when scattered through the codebase. – mabraham Jan 25 '16 at 18:44
0

I recent workaround I found that maybe helps with your problem is by using: __has_include, which seems to be available in GCC, Clang and VS.

#if defined(__has_include)
#if __has_include(<sanitizer / lsan_interface.h>)
#include <sanitizer/lsan_interface.h>

void *p = create_new_object();
__lsan_ignore_object(p);
#endif
#endif
Anastasios Andronidis
  • 6,310
  • 4
  • 30
  • 53