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.
Use the LeakSanitizer for finding memory leaks in your own applications.
Download a release here and link your application with the prebuilt framework.
Alternatively, you can build it yourself.
Use the LeakSanitizer by linking with its framework. On Linux, link with the runtime library directly.
Either embed the framework into your application or add the directory where you have put the LeakSanitizer's framework to the framework search path and the runtime search path of your application.
Tip
Example of the necessary compiler flags for Apple's Clang compiler on macOS:
-F<path/to/LeakSanitizer> -rpath <path/to/LeakSanitizer> -framework LeakSanitizer
Add the runtime library of the LeakSanitizer to your linking arguments.
Tip
Example for standard C/C++ compilers:
-L<path/to/LeakSanitizer> -llsan
You can also inject the runtime library into a process by adding it to the preload environment variable of your dynamic linker:
- Linux:
LD_PRELOAD=<path/to/LeakSanitizer>/liblsan.so - macOS:
DYLD_INSERT_LIBRARIES=<path/to/LeakSanitizer>/LeakSanitizer.framework/LeakSanitizer
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> -llsanthis example creates the following output:
Compiled and linked on Fedora with the command
gcc -g test.c -L<path/to/LeakSanitizer> -llsanthe example above creates the following output:
Tip
Indirect memory leaks can be displayed by setting LSAN_INDIRECT_LEAKS to true:
LSAN_INDIRECT_LEAKS=trueReachable memory leaks (those to which a pointer was found) can be hidden by setting LSAN_REACHABLE_LEAKS to
false:
LSAN_REACHABLE_LEAKS=falseTo 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)
.dSYMMach-O bundles
The DWARF parser supports DWARF in version 2, 3, 4 and 5.
Since version 1.6 the behavior 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_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_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_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 freed |
v1.6 | Boolean | false |
LSAN_ZERO_ALLOCATION |
Issue a warning when 0 byte are allocated |
v1.8 | Boolean | false |
LSAN_STATS_ACTIVE |
Enable the statistical bookkeeping | v1.6 | Boolean | false |
LSAN_AUTO_STATS |
Time interval between the automatic statistics printing | v1.11 | Time interval | None |
LSAN_SUPPRESSION_DEVELOPER |
Activates more suppression developer output | v1.11 | Boolean | false |
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 crash is printed. |
Your own signal handlers take precedence. 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.
Get started by downloading a release. Alternatively, you can build the LeakSanitizer from source.
Simply move the downloaded framework anywhere you like, for example into the directory /Library/Frameworks.
Simply move the headers and the library anywhere you like.
For example, the headers can be moved into the directory /usr/local/include and the library into the directory
/usr/local/lib.
Clone the repository:
git clone --recurse-submodules https://github.com/mhahnFr/LeakSanitizer.git && cd LeakSanitizerBuild the framework using the following command:
xcodebuildUpon successfully building the framework, it can be found in the directory ./build/Release. You can also specify
another build directory by passing the option -derivedDataPath <desiredBuildPath> to the preceding command.
Tip
Example:
xcodebuild -derivedDataPath <path/to/build/folder>The framework LeakSanitizer.framework will then be located in the directory <path/to/build/folder>/Release.
Build the library by using GNU Make:
makeIt 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 installAdapt the value of the INSTALL_PATH argument to your needs.
Tip
To create a portable build (just like the downloaded release), use the following command:
make releaseThe LeakSanitizer adheres to the standard of C++23.
Additionally, the following command line tools are necessary to successfully build the LeakSanitizer:
- GNU compatible
makecommand line tool - The
catcommand line tool (POSIX.2)
All dependencies introduced by the CallstackLibrary are needed as well.
To uninstall the LeakSanitizer, on macOS, simply remove the framework from the installation directory.
On Linux, simply remove its headers and its library. This can be done by the following command:
make INSTALL_PATH=/usr/local uninstallAdapt the value of the INSTALL_PATH argument to your needs.
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 caused by the LeakSanitizer itself are ignored.
The signal handlers and the wrapper functions are installed once the sanitizer has been loaded by the dynamic linker. Your own signal handlers take precedence.
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 - 2026 mhahnFr and contributors