1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
DEBAUCH:
Debauch is a malloc debugger. It is based on code from "memleak" from the
XFree86 distribution (originally by Keith Packard of the MIT X
Consortium), but has been significantly altered such that a name change
seemed appropriate. The name debauch was chosen in contrast to a
commercial memory debugger "purify", and for a bad pun with de-botch
(i.e. help you fix places where you've botched your code).
Debauch consists of a dynamic library (libdebauch.so) and a shell script.
The shell script relies on the run-time linker understanding LD_PRELOAD
such that libdebauch.so's memory allocation functions will override the
standard C ones.
The advantage of this approach over other memory-debugging libraries is
that most other memory debuggers require wrapping malloc / realloc /
calloc / free with customized versions, which requires a
recompile relink. The wrapping approach also will not work for C library
functions such as strdup without re-compiling the C library (and any other
libraries such as X, Xt, etc) with the wrapped versions.
Debauch will catch *any* calls to malloc and friends since it overrides
the versions defined in the C library, and best of all, it doesn't require
manually relinking your application, but relies on the run-time linker to
handle that for you.
Debauch's library replaces the C library allocator; providing malloc,
free, realloc and calloc (sorry, no valloc).
In doing so, it provides extensive memory bug checking, locating:
Lost memory; memory which has not been freed and which has no
references. This type of memory will become leaked memory on program
exit.
In use free memory; memory which has been freed and still has references
to it.
Stores to freed memory. This indicates an error in your program's logic.
Calls to free/realloc with invalid pointers -- if you pass in a pointer
to the middle of an allocated block, it will even tell you which one.
For each of these errors, a report entry is generated which includes
the stack backtrace of either the allocation or free (which ever occured
last) along with the current stack, when relevant. Note that the stack
trace is *NOT* necessarily for when the error occurs. For example a store
into free memory can happen anytime after the memory has been freed, but
the stack trace will still be for the free() call. If you wish to detect
such errors, you should consider using ElectricFence, which provides such
a capability, but doesn't detect leaks.
Unreferenced allocated memory, stores to freed memory and referenced freed
memory are only caught when CheckMemory is called. It is automatically
called each time 1m of data has been freed, and is called when the program
exits (by registering with atexit(3)/on_exit(3)). If you link against
libdebauch.so, your program can call CheckMemory manually whenever you want.
There are several global variables which alter the behavior of debauch.
These values can be initialized from environment variables of the same
name. The environment variables should be set to 1 or 0 to turn the
behavior on or off, respectively.
DebauchWarnReferenced
Warn about free'd memory which is still referenced.
Programs may accidentially refer to this memory later, but
in most cases this is not a problem. The debauch shell
script defaults to turning this off.
DebauchWarnUnreferenced
Warn about malloc'd memory to which there are no
references, this may become "lost" memory (a memory
leak). Since leaks will be reported at the end, the
debauch shell script defaults to turning this off.
DebauchWarnMiddlePointers
Normally, memleak ignores pointers to the middle of
freed memory. These are frequently simply random data
which happens to look like a pointer. Turning this
on will generate additional messages.
DebauchCheckAlways
When set, memleak checks the entire memory system after
each allocation or free. This is very expensive, but
may catch errors not otherwise found until too late.
Serial event tracing: These variables are more useful when running inside
a debugger, or if the source to your program has been specially modified
to use debauch. Debauch assigns a serial number to each malloc/free
event and stores it in the allocation header. You can use this serial
number to control Debauch's output:
DebauchAllocBreakpoint
At each allocation, Debauch increments a serial number
and stores it in the allocation header. By rerunning
the program, you can stop when that piece of memory
is going to be allocated. Store the serial number
in this global variable and put a debugger breakpoint inside
AddActiveBlock at the indicated line.
DebauchFreeBreakpoint
Similarly for freeing memory.
DebauchTime
The current serial number. (Not settable via an
environment variable.)
DebauchErrorTime:
This variable will cause debauch not to print error
messages from malloc/free events before the specified
time. You may wish to use this if your program does
extensive allocation to initialize (e.g. an X11 program),
which you're not concerned about. Within the running
program (or via the debugger) you can set
DebauchErrorTime=DebauchTime, and no events prior to the
current counter will be printed when CheckMemroy is called
or when the program exits. You may also initialize
DebauchErrorTime from an environment variable of the same
name.
USER-CALLABLE Routines:
DebauchStart: (extern int DebauchStart(void);)
Client programs may call this routine to set error
reporting to ignore memory allocated or freed before the
current time. This requires the client program to be
re-compiled. Alternately, this routine may be called from a
debugger at a suitable time. Errors occuring *before* this
routine are still recognized internally; but messages about
them are supressed.
INVOCATION:
The simplest way of running debauch is by using the shell script:
unix% debauch [-a] myprog [myprog args]
The -a flag to debauch specifies that you want debauch to give all
warnings, including possible references to freed memory and
unreferenced but unfree'd memory.
Debauch will run the program with LD_PRELOAD set to load libdebauch.so.
This will generate a report on possible memory errors and generate a stack
trace of return addresses. In order to turn this stack trace into
file:line information, debauch runs gdb to extract the relevant information.
If the target program wasn't compiled with "-g" the file/line information
will be missing, but the stack trace will at least be modified to show the
names of the routines. You can then analyze the output to find the leaked
memory and modify your program to free it.
TODO:
There are several changes I'd like to see in debauch; if you'd like to
help out, consider doing one of the following:
o porting to other platforms; see PORTING below. Ports are actively
solicited.
o using GNU-style configure script instead of Imakefiles
o The stack trace doesn't have the contents of the offending line,
just the file and line number. In theory, one should be able to
get the contents of the line to be in the stack trace as well as
the file:line information. Unfortunately, GDB doesn't provide this
information in an easily parsable manner. Instead of "info line
*address", you should be able to use "list *address" in gdb, but
you get 10 lines around the line you want. You should be able to
do a "set listsize 1" and then (e.g.) "list 10", but my version of
GDB has a bug (or misfeature) which prevents GDB from generating
output with listsize=1; listsize must be at least 2. If you want
to modify the debauch script to parse such a listing and return only
the text of the line of interest for including in the stacktrace,
I'd certainly include it.
PORTING:
To port debauch to a new machine, you must provide two values, one
indicating the lowest data address in a program (BottomOfData) and one
indicating the highest stack address (TopOfStack). In addition, to get
return stack traces (which are almost essential for debugging), you must
provide the function getReturnStack. Samples for Linux, BSDi386, MIPS,
SPARC are included already. The linux code is new and is known to work
BSD, MIPS and SPARC are from XFree86's memleak and either don't work, or
have not been tested.
MIPS:
The MIPS code doesn't work with SGI O2's, and possibly other
platforms, probably because BOTTOM_OF_DATA or endOfStaticMemory is
defined incorrectly. Also, SGI doesn't support LD_PRELOAD, but
_RLD_LIST "/path/libdebauch.so:DEFAULT" will work. See man rld
for more hints on using _RLD_LIST.
|