memtool -- diagnose dynamic memory allocation errors


memtool [-flnqsvwxz] [-a argno] [-d depth] [-i ignsigs]
   [-o file] command [command_arguments ...]


memtool helps you find and diagnose dynamic memory allocation bugs in your program. You start your application just as usual, except that you run it through memtool. For example:
   $ memtool your_prog its_args

memtool analyzes and reports detailed information about the following misuses of allocated memory:

In this context, ``blocks'' are the individual objects that comprise the allocation ``arena'' -- the objects whose addresses are returned by malloc(3C) or new(3C++std).


Options to memtool adjust its behavior to help you diagnose specific problems:

-a argno
cause memtool to store argno ``words'' (3 by default) for each function in each stack trace.

-d depth
cause memtool to limit the stack traces to depth functions. By default, complete stack traces are saved.

cause memtool to track the child processes of your application. By default, memtool only manages the initial process.

-i ignsigs
cause memtool to ignore the delivery of the specified signal numbers. ignsigs is a list of signals separated by a space or comma. memtool emits information about the state of your application when it detects the delivery of any unignored signals. See the -s option as well.

cause memtool to not list ``leaked'' blocks. These are the blocks still available for your application to use as your application exits.

cause memtool to make null pointer references generate segmentation faults.

-o <file>
cause memtool to write its diagnostic information to file instead of the standard error output.

cause memtool to emit briefer diagnostic messages.

cause memtool to not display information regarding the delivery of signals to your application. See the -i option as well.

cause memtool to emit longer messages. In particular, you get a very long introductory message before the first detected misuse with this option. If combined with -q, the -v option has no effect.

cause memtool to perform complete walks through the allocation arena for each call to the malloc(3C) routines. This can cause a noticeable slow-down in your application.

cause memtool to change every allocation so a few extra bytes are allowed at the end of the block. This can be useful in changing when and where an inappropriate block modification takes place and when it is detected. If -x is not specified, memtool does not change the block sizes and addresses used in your application.

cause memtool to warn when zero (or null) arguments are passed to the malloc( ) routines. By default, these are silently accepted, as normal.


memtool provides the best information when the application has been built with debugging information; see the -g option to cc(1) or CC(1C++). It is not, however, necessary to build your program in any special way to use memtool; all that is required is that it use the dynamic C library malloc(3C) directly or indirectly (such as through the C++ new(3C++std) routines) and can be processed by debug(1).

memtool can only detect dynamic memory misuses as provided by the checking features documented in malloc(3C). For example, it cannot detect general pointer misuses, the overrunning of local or global arrays, or distinguish between intended and unintended use of a block.

Each diagnostic includes one to three stack traces:

If the misuse is an inappropriately modified block, an annotated memory snapshot of the block is also provided, highlighting where the block was found to have been modified.


memtool is written to have minimal impact on the execution of the program being analyzed. Unless you use the -x option, all addresses returned for the malloc(3C) routines are unchanged, although most stack addresses are modified. The application is also being run under the control of debug(1), which is particularly noteworthy for applications that are timing-sensitive, such as those that use threads. memcopy can consume large chunks of mmap(2) virtual space for the internal sanity checking in the malloc(3C) routines. Applications usually run slower under memtool, especially when the -w option is used.


Given the following contrived C source code
   $ cat bad.c
   #include <stdlib.h>
   static void *f(void *p) {
   	return malloc(0);
   int main(void) {
   	char *p = malloc(13);
   	p[13] = 'x';
   	p = realloc(p, 7);
   	return 0;
Building it and running it, we see nothing wrong:
   $ cc -g -o bad bad.c
   $ ./bad
   $ echo $?
But, if run with memtool:
   $ memtool ./bad
we get nearly a hundred lines of diagnostics, including the following. Note that bad.c was compiled with the -g option to generate debugging information, so the memtool output is more detailed than it would otherwise be.
   A block's spare bytes have been modified.  This usually occurs due to
   writing beyond the block's regular bytes, either because an insufficient
   number of bytes were requested when the block was allocated or simply
   due to a programming logic error.

History for block at address 0x80496f8: *Stack trace when detected: [0] free(ptr=0x80496f8) [1] f(p=0x80496f8) [bad.c@3] in ./bad [2] main(0x1,0x8047a34,0x8047a3c) [bad.c@9] in ./bad [3] _start() [0x804856c] in ./bad

*Stack trace when block at 0x80496f8 was allocated: [0] malloc(sz=13) [1] main() [bad.c@7] in ./bad [2] _start(presumed:0x1,0x8047a34,0x8047a3c) [0x8048571] in ./bad

Annotated snapshot surrounding the live allocation at address 0x80496f8 when the byte at 0x8049705 was found to have been modified. This allocation holds 13 bytes followed by 7 extra (or spare) bytes, and, in this case, a spare byte was found to have been modified.

0x80496f0: 0x08047a34 0x00000019 0xcacacaca 0xcacacaca 4z.............. : ******** -------- -------- ****-------- 0x8049700: 0xcacacaca 0xcaca78ca 0xcacacaca 0x0000001d .....x.......... : -------- ++++^^-- ++++++++ -----^++++++

as well as a complaint about the misuse of realloc():
   A recently free()d block was passed as the first argument to realloc().
   Only null pointers or live block addresses are permitted to be passed to
   realloc(), although, in this implementation, were dynamic memory checking
   not enabled, this block's contents would have been preserved between its
   being freed and this call to realloc(), but this is a nonportable feature
   of this implementation which should not be relied on.

History for block at address 0x80496f8: *Stack trace when detected: [0] realloc(ptr=0x80496f8,sz=7) [1] main(0x1,0x8047a34,0x8047a3c) [bad.c@10] in ./bad [2] _start() [0x804856c] in ./bad

*Stack trace when block at 0x80496f8 was released: [0] free(ptr=0x80496f8) [1] f(p=0x80496f8) [bad.c@3] in ./bad [2] main() [bad.c@9] in ./bad [3] _start(presumed:0x1,0x8047a34,0x8047a3c) [0x8048571] in ./bad

*Stack trace when block at 0x80496f8 was allocated: [0] malloc(sz=13) [1] main() [bad.c@7] in ./bad [2] _start(presumed:0x1,0x8047a34,0x8047a3c) [0x8048571] in ./bad

There were also complaints about two leaked blocks. If the -z option were used, memtool would also generate a warning about the malloc(0) on line 4. Because bad.c was compiled with the -g option to generate debugging information, the memtool output includes the source file and line number in the stack trace lines as well as the parameter names. Had the code been compiled without -g, each function would show three hexadecimal arguments. memtool can be run on a stripped program, but the output will not show even the function names.


cc(1), CC(1C++), debug(1), truss(1)

malloc(3C), new(3C++std)

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 25 April 2004