% mpr perl -e 'print "goodbye, cruel world\n"' % mpr python -c 'print "goodbye, cruel world"' % mpr tcl -c 'puts "goodbye, cruel world"' % mpr lua -e 'print "goodbye, cruel world"'
If your program has not been linked against libmpr.a or libmpr.so, mpr will add libmpr.so to the environment variable LD_PRELOAD to force libmpr.so to be loaded before your program runs.
If the MPRFI environment variable is unset, mpr will set it to "gzip -1 >log.%p.gz". This will save the log messages to a file named log.pid.gz in the current directory, where pid is the process ID of the process that executes your program. If your program creates child processes, there may be multiple log files created. See the MPRFI section below for details on MPRFI, and the MPRNOCHILD section below for details on how to disable tracing child memory allocations.
NOTE: If mpr cannot find libmpr.so, it will print an error message to stderr and exit without running your program - you will need to manually set the environment variable LD_LIBRARY_PATH to include the directory containing libmpr.so.
NOTE: On NetBSD, you will need to manually set the environment variable MPRLD_PRELOAD to the complete path name for libmpr.so, since ld.elf_so(1) on NetBSD does not search LD_LIBRARY_PATH for LD_PRELOAD objects.
If you use the wrapper mpr to run your program and
MPRFI is not already set, it will be set to
If you only wish to catch memory leaks (i.e. if you are not interested in your program's entire allocation history), you can use mprleak in MPRFI:
% env MPRFI='mprleak >leaks.%p' mpr a.out ...
If you have statically linked libmpr.a into your program, you can disable the mpr hook functions by unsetting MPRFI or setting it to the empty string:
% env MPRFI= a.out ...
% env MPRNOCHILD=1 a.out ...
% mprmap a.out <log % mprmap a.out log % mprmap a.out log.gz
To examine memory leaks, use mprleak as a pre-filter:
% mprleak log | mprmap a.out
Use option -i if you have "wrapper" functions around calls to malloc()/free() that are cluttering your call chains. Its argument is a list of comma-separated functions that you wish to ignore.
void *xmalloc(size_t sz) { void *p = malloc(sz); if (!p && sz) abort(); return p; } void *xrealloc(void *ptr, size_t sz) { void *p = realloc(ptr, sz); if (!p && sz) abort(); return p; }
In the code fragment above, xmalloc()/xrealloc() are wrappers around malloc()/realloc() that check for allocation failures. Since they are not directly responsible for the allocations, you can ignore them with:
% mprmap -i xmalloc,xrealloc ...
As indicated above, "," (comma) is the default separator for the list of functions to be ignored with option -i. If you are using mprmap with a C++ program, you can use option -I to specify a different separator since "," may appear in a C++ function's signature:
% mprmap -I'#' -i 'objalloc(void *, size_t)#objalloc(size_t)' a.out log
Option -f displays file names in addition to function names. This only works for those parts of your program that were compiled with the -g option of the C compiler. Parts of your program that were not compiled with -g, or whose symbol tables have been stripped, will not display file names. Option -l displays line numbers in addition to file names and function names - it should be used in conjunction with option -f.
% mprmap -f -l -i xmalloc,xrealloc a.out log
Option -F is similar to option -f, but it restricts the set of source files for which file names are displayed. For example, to display file names and line numbers only for files a.c and b.c:
% mprmap -F a.c,b.c -l a.out log
To display file names and line numbers only for source files in directory src/dir1:
% mprmap -F "`cd src/dir1; echo *.c`" -l a.out log
Option -p is useful if you are using mprmap with a C++ program. By default, mprmap will print the full signature of each C++ function - this can result in unwieldy looking output. Option -p omits the parameter list portion of the signature.
% mprmap a.out log | mprchain
To see memory leaks grouped by call chains, use mprleak as a pre-filter to mprmap:
% mprleak log | mprmap a.out | mprchain
mprchain displays the call chain in column 1, the number of allocations/leaks by the call chain in column 2, the total amount of memory allocated/leaked by the call chain in column 3, and the percentage of memory allocated/leaked by the call chain in column 4. mprchain also prints a separator line "--" between each call chain, which helps to distinguish between call chains that span multiple lines.
Option -c sets the length of the call chains (default=999999).
% mprmap -f -l a.out log | mprchain -c9
Option -C sets the number of call chain entries to display per line. By default, mprchain tries to squeeze as many entries as it can onto one line.
% mprmap -f -l a.out log | mprchain -C1
Option -w sets the width of the display (default=80).
% mprmap -f -l a.out log | mprchain -w132
Option -n omits the percentage column.
Option -m displays, in column 3, the maximum amount of memory that was allocated at any time by the call chain (instead of the total amount of memory allocated by the call chain).
main() { int i; char *p1, *p2; for (i=0; i<10; i++) { p1 = malloc(200); free(p1); } p1 = malloc(150); p2 = malloc(100); free(p1); free(p2); }
In the code fragment above, without option -m, mprchain will show main() as having allocated a total of 2250 bytes; with option -m, it will show main() as having allocated a maximum of 250 bytes.
% mprsize <log % mprsize log % mprsize log.gz
To see memory leaks grouped by size, use mprleak as a pre-filter.
% mprleak log | mprsize
mprsize displays the size in column 1, the number of allocations/leaks of that size in column 2, the amount of memory allocated/leaked by that size in column 3, and the percentage of memory allocated/leaked by that size in column 4.
Option -n omits the percentage column.
% mprleak <log | mprmap a.out % mprleak log | mprmap a.out % mprleak log.gz | mprmap a.out
To examine memory leaks grouped by call chains:
% mprleak log | mprmap a.out | mprchain
To examine memory leaks grouped by size:
% mprleak log | mprsize
If you only wish to catch memory leaks in your program (i.e. if you are not interested in your program's entire allocation history), you can use mprleak in MPRFI.
% env MPRFI='mprleak >leaks.%p' mpr a.out ...
% mprhisto <log % mprhisto log % mprhisto log.gz
mprhisto uses "*" (asterisk) to represent a 1KB block of allocated memory. For example, to find the maximum amount of memory (within 1KB) that was allocated at any point during the life of your program:
% mprhisto log | awk '{if (length>m) m=length} END {print m}'
Use option -b to change the default block size. For example, to see a histogram with a block size of 2KB:
% mprhisto -b2048 log
Option -c sets the length of the call chains to display alongside the histogram (by default, no call chains are displayed). If you use option -c, you should pre-filter the MPRFI log file through mprmap so that call chain program counters are mapped to function names. For example, to see a histogram with a block size of 2KB and call chains of length 5:
% mprmap a.out log | mprhisto -b2048 -c5
Note that without option -c, mprhisto will not show adjacent histogram entries of the same length (i.e. mprhisto only shows changes in the amount of allocated memory in multiples of the block size). If you use option -c, mprhisto is more verbose and prints a line for every malloc()/free() (i.e. every line in the MPRFI log file).
Option -w sets the width of the display (default=80), and is useful when you use option -c to show call chains alongside the histogram. With option -c, mprhisto tries to right justify the call chains to line up in column 80 (the histogram is easier to visualize by separating it from the call chains). However, if the output scrolls off the end of the screen or if the call chains are too close to the histogram, you can
For example, to see a histogram with a block size of 2KB and call chains of length 5 on a 132-column wide display:
% mprmap a.out log | mprhisto -w132 -b2048 -c5
The quality of your AWK interpreter can make a big difference to the runtime of mprmap. I suggest that you install Michael Brennan's excellent mawk on your system. Even GNU gawk, which is the standard AWK interpreter on most Linux systems, loses - I have seen improvements of over 500% using mawk vs gawk. For example, to force all the mpr scripts to use mawk:
% export MPRAWK='mawk -W sprintf=4096'
% export MPRTMP=$HOME/tmp
% env MPRSYNC=1 MPRFI=mprhisto mpr a.out
You may need to force your awk interpreter to unbuffer or line-buffer stdout in order for this to work. For example, if you're using mawk:
% env MPRAWK='mawk -W interactive' MPRSYNC=1 MPRFI=mprhisto mpr a.out
% export MPRSH=/bin/ksh
% export MPRLD_PRELOAD=/usr/local/lib/libmpr.so