Tool to track down memory leaks.
It can be used in conjunction with code written in almost any programming language that compiles down to native machine
code.
Officially supported languages are currently:
- C
- C++
- Objective-C
- Swift
This tool is available for both Linux and macOS.
Get started by downloading a release.
Simply move the headers and the library anywhere you like.
Alternatively, you can build the LeakSanitizer from source:
git clone --recurse-submodules https://github.com/mhahnFr/LeakSanitizer.git && cd LeakSanitizer && make
It is automatically installed in the directory where the LeakSanitizer was cloned in. To install it in a specific directory, use the following command:
make INSTALL_PATH=/usr/local install
Adapt the value of the INSTALL_PATH
argument to your needs.
Tip
To create a portable build (just like a downloaded release), use the following command:
make release
The LeakSanitizer adheres to the standard of C++17.
Additionally, the following command line tools are necessary to successfully build the LeakSanitizer:
- GNU compatible
make
command line tool - The
uname
command line tool (POSIX.2) - The
cat
command line tool (POSIX.2)
All dependencies introduced by the CallstackLibrary are needed as well.
To uninstall the LeakSanitizer, simply remove its headers and its library from the installation directory.
This can be done by the following command:
make INSTALL_PATH=/usr/local uninstall
Adapt the value of the INSTALL_PATH
argument to your needs.
Use this tool by preloading its runtime library or by linking against it (recommended).
Add the runtime library of the LeakSanitizer to your linking arguments.
Tip
Example for standard C/C++ compilers:
-L<path/to/LeakSanitizer> -llsan
Add the runtime library to the preload environment variable of your dynamic linker:
- Linux:
LD_PRELOAD=<path/to/LeakSanitizer>/liblsan.so
- macOS:
DYLD_INSERT_LIBRARIES=<path/to/LeakSanitizer>/liblsan.dylib
Once this sanitizer is bundled with your application the detected memory leaks are printed upon termination.
Example:
// test.c
#include <string.h>
#include <stdlib.h>
char* global;
void foo2(void) {
global = strdup("Global variable");
}
void bar2(void) {
void* a = malloc(1023);
a = strdup("Hello World!");
a = NULL;
a = malloc(1000);
free(a);
foo2();
}
void foo(void) { bar2(); }
void bar(void) { foo(); }
int main(void) {
bar();
}
Compiled and linked on macOS with the command
cc -g test.c -L<path/to/LeakSanitizer> -llsan
this example creates the following output:
Compiled and linked on Fedora with the command
gcc -g test.c -L<path/to/LeakSanitizer> -llsan
the example above creates the following output:
Tip
Indirect memory leaks can be displayed by setting LSAN_INDIRECT_LEAKS
to true
:
LSAN_INDIRECT_LEAKS=true
Reachable memory leaks (those to which a pointer was found) can be hidden by setting LSAN_REACHABLE_LEAKS
to
false
:
LSAN_REACHABLE_LEAKS=false
To add source file line information to the output (as shown above), simply compile your target with debug symbols.
Tip
Usually, the appropriate compilation option is -g
.
Currently, debug symbols in the following formats are supported:
- DWARF in ELF binary files
- DWARF in Mach-O debug maps (using Mach-O object files)
.dSYM
Mach-O bundles
The DWARF parser supports DWARF in version 2, 3, 4 and 5.
Since version 1.6 the behaviour of this sanitizer can be adjusted by setting certain environment variables.
The following variables are currently supported:
Name | Description | Since | Type | Default value |
---|---|---|---|---|
LSAN_HUMAN_PRINT |
Print human-readably formatted | v1.6 | Boolean | true |
LSAN_PRINT_COUT |
Print to the default output stream | v1.6 | Boolean | false |
LSAN_PRINT_FORMATTED |
Print using ANSI escape codes | v1.6 | Boolean | true |
LSAN_INVALID_CRASH |
Terminate if an invalid action is detected | v1.6 | Boolean | true |
LSAN_INVALID_FREE |
Detect invalid deallocations | v1.6 | Boolean | true |
LSAN_FREE_NULL |
Issue a warning if NULL is free d |
v1.6 | Boolean | false |
LSAN_STATS_ACTIVE |
Enable the statistical bookkeeping | v1.6 | Boolean | false |
LSAN_CALLSTACK_SIZE |
The amount of frames to be printed in a callstack | v1.6 | Number | 20 |
LSAN_PRINT_EXIT_POINT |
Print the callstack of the exit point | v1.7 | Boolean | false |
LSAN_PRINT_BINARIES |
Print the binary file names | v1.8 | Boolean | true |
LSAN_PRINT_FUNCTIONS |
Always print the function names | v1.8 | Boolean | true |
LSAN_RELATIVE_PATHS |
Allow relative paths to be printed | v1.8 | Boolean | true |
LSAN_ZERO_ALLOCATION |
Issue a warning when 0 byte are allocated |
v1.8 | Boolean | false |
LSAN_AUTO_STATS |
Time interval between the automatically statistics printing | v1.11 | Time interval | None |
LSAN_SUPPRESSION_DEVELOPER |
Activates more suppression developer output | v1.11 | Boolean | false |
LSAN_INDIRECT_LEAKS |
Whether to print indirectly leaked allocations | v1.11 | Boolean | false |
LSAN_REACHABLE_LEAKS |
Whether to print leaks to whose a pointer was found | v1.11 | Boolean | true |
LSAN_SUPPRESSION_FILES |
List of additional suppression files to be considered | v1.11 | File list | None |
LSAN_SYSTEM_LIBRARY_FILES |
List of additional system library files to be considered | v1.11 | File list | None |
Tip
LSAN_AUTO_STATS
should be assigned a number with a time unit directly after the number.
The following time units are available:
ns
: nanosecondsus
: microsecondsms
: millisecondss
: secondsm
: minutesh
: hours
The default unit when none is given is seconds.
More on the environment variables here.
Use the memory leak suppression system introduced in version 1.11 to "remove" internal memory leaks created by the runtime libraries you additionally use.
Add your additional suppression files to the environment variable LSAN_SUPPRESSION_FILES
.
Tip
Example:
LSAN_SUPPRESSION_FILES='someLibrarySuppressions.json:otherIgnoredLeaks.json'
Follow the full documentation of the suppression system in order to write your own suppression files.
This sanitizer comes with handlers for the following signals:
Signal | Action |
---|---|
SIGUSR1 |
Prints the statistics if enabled using LSAN_STATS_ACTIVE or LSAN_AUTO_STATS . |
SIGUSR2 |
Prints the current callstack. |
Any deadly signal | is caught and the stacktrace of the cash is printed. |
More about the signal handlers here.
The statistics of the tracked memory can be queried at runtime. To do so activate the statistical bookkeeping by either
setting the environment variable LSAN_STATS_ACTIVE
to true
or by using LSAN_AUTO_STATS
.
The statistics then can be queried using the following API:
Function | Description |
---|---|
__lsan_getTotalMallocs() |
Returns the total count of allocations registered. |
__lsan_getTotalBytes() |
Returns the total count of allocated bytes. |
__lsan_getTotalFrees() |
Returns the total count of registered allocations that have been deallocated. |
__lsan_getCurrentMallocCount() |
Returns the count of currently active allocations. |
__lsan_getCurrentByteCount() |
Returns the amount of currently allocated bytes. |
__lsan_getMallocPeek() |
Returns the highest amount of allocations at the same time. |
__lsan_getBytePeek() |
Returns the highest amount of bytes allocated at the same time. |
__lsan_printStats() |
Prints the statistics to the output stream specified by LSAN_PRINT_COUT . |
__lsan_printFStats() |
Prints the fragmentation statistics to the output stream specified by LSAN_PRINT_COUT . |
More on the statistics here.
In order to track the memory allocations this sanitizer replaces the common allocation management functions such as
malloc
, calloc
, realloc
and free
. Every allocation and deallocation is registered and a stacktrace is created
for it.
The allocations created by the LeakSanitizer are ignored.
The signal handlers and the wrapper functions are installed once the sanitizer has been loaded by the dynamic linker.
When the exit handler registered using atexit
is invoked the allocated memory is examined and the detected memory
leaks are printed.
The stacktraces are managed using the CallstackLibrary.
If you experience any problems with the LeakSanitizer or if you have ideas to further improve it do not hesitate to open an issue or to open a pull request.
This project is licensed under the terms of the GNU GPL in version 3 or later.
© Copyright 2022 - 2025 mhahnFr and contributors