-
Notifications
You must be signed in to change notification settings - Fork 1k
AddressSanitizerLeakSanitizer
LeakSanitizer is a memory leak detector which is integrated into AddressSanitizer. The tool is supported on x86_64 Linux and OS X.
LeakSanitizer is enabled by default in ASan builds of x86_64 Linux, and can be enabled with ASAN_OPTIONS=detect_leaks=1
on x86_64 OS X. LSan lies dormant until the very end of the process, at which point there is an extra leak detection phase. In performance-critical scenarios, LSan can also be used without ASan instrumentation.
See also: design document, comparison with tcmalloc's heap leak checker
To use LSan, simply build your program with AddressSanitizer:
$ cat memory-leak.c
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
$ clang -fsanitize=address -g memory-leak.c
$ ./a.out
=================================================================
==7829==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#0 0x42c0c5 in __interceptor_malloc /usr/home/hacker/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
#1 0x43ef81 in main /usr/home/hacker/memory-leak.c:6
#2 0x7fef044b876c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).
If you want to run an ASan-instrumented program without leak detection, you can pass detect_leaks=0
in the ASAN_OPTIONS
environment variable.
If you just need leak detection, and don't want to bear the ASan slowdown, you can build with -fsanitize=leak
instead of -fsanitize=address
. This will link your program against a runtime library containing just the bare necessities required for LeakSanitizer to work. No compile-time instrumentation will be applied.
Be aware that the stand-alone mode is less well tested compared to running LSan on top of ASan.
You can fine-tune LeakSanitizer's behavior through the LSAN_OPTIONS
environment variable.
flag | default | description |
---|---|---|
exitcode | 23 | If non-zero, LSan will call _exit(exitcode) upon detecting leaks. This can be different from the exit code used to signal ASan errors. |
max_leaks | 0 | If non-zero, report only this many top leaks. |
suppressions | (none) | Path to file containing suppression rules (see below) |
print_suppressions | 1 | If 1, print statistics for matched suppressions. |
report_objects | 0 | If 1, LSan will report the addresses of individual leaked objects. |
use_unaligned | 0 | If 0, LSan will only consider properly aligned 8-byte patterns when looking for pointers. Set to 1 to include unaligned patterns. This refers to the pointer itself, not the memory being pointed at. |
Leak detection is also affected by certain ASan flags. If you're not happy with the stack traces you see, check out fast_unwind_on_malloc
, malloc_context_size
and strip_path_prefix
. Those flags go in ASAN_OPTIONS
as usual. However, if you built with -fsanitize=leak
, put them in LSAN_OPTIONS
instead (and use LSAN_SYMBOLIZER_PATH
to pass the symbolizer path).
You can instruct LeakSanitizer to ignore certain leaks by passing in a suppressions file. The file must contain one suppression rule per line, each rule being of the form leak:<pattern>
. The pattern will be substring-matched against the symbolized stack trace of the leak. If either function name, source file name or binary file name matches, the leak report will be suppressed.
$ cat suppr.txt
# This is a known leak.
leak:FooBar
$ cat lsan-suppressed.cc
#include <stdlib.h>
void FooBar() {
malloc(7);
}
void Baz() {
malloc(5);
}
int main() {
FooBar();
Baz();
return 0;
}
$ clang++ lsan-suppressed.cc -fsanitize=address
$ ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=suppr.txt ./a.out
=================================================================
==26475==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 5 byte(s) in 1 object(s) allocated from:
#0 0x44f2de in malloc /usr/home/hacker/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
#1 0x464e86 in Baz() (/usr/home/hacker/a.out+0x464e86)
#2 0x464fb4 in main (/usr/home/hacker/a.out+0x464fb4)
#3 0x7f7e760b476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
-----------------------------------------------------
Suppressions used:[design document](AddressSanitizerLeakSanitizerDesignDocument)
count bytes template
1 7 FooBar
-----------------------------------------------------
SUMMARY: AddressSanitizer: 5 byte(s) leaked in 1 allocation(s).
The special symbols ^
and $
match the beginning and the end of string.