DB ALLOC:    A Memory-leak and Fence-post Malloc Debug Library

Copyright © 2001 Peter MacDonald. Download Current Version: 1.0

DB Alloc is a minimalistic malloc frontend that performs the following checks: memory-leaks, fence-post writes, freed memory writes and duplicate calls to free. It currently checks only malloc, calloc, realloc, strdup and free. The fence-post checking is similar to what is provided by DMalloc but at 700 lines, is small enough to be left linked in, and simple enough to use under Win32 with the Ming cross compiler. There is also an optional Tcl interface. DB Alloc can be used freely under the Artistic License. See http://browsex.com for details

DB Alloc can be used as either a compiled in wrapper that #defines malloc and cousins, or as a link library that chains to the real malloc code after the checks, or both ways at the same time. Under GNU LIBC it uses the __libc_malloc functions. Under Windows, it uses LoadLibrary/GetProcAddress.

To use without including dballoc.h in your sources link with dballocl.o. Errors this way will give only the hex return address but you can use with gdb and info line *0xNNNNN to get the source line number. You may also build and use as a shared library.

The alternative wrapper method requires recompiling to obtain the file and line number directly from the allocation call. This supports debugging allocations for a subset of a program, and requires that you to include the "dmalloc.h" header in some/all source files and link with either dballoc.o or dballocl.o. The header file #defines malloc to _db_heap_malloc, etc. The regular malloc can still be used in tandem, elsewhere. Note that for dballoc.o, each wrapped malloc requires a corresponding call to wrapped free or the results are unpredictable. The library attempts to identify and deal with such cases, but I wouldn't count on it.

DB Alloc redefines malloc, calloc, realloc, and strdup to build a list of allocations. It can then do fence-post checking for pointers that have overwriten their bounds. Checking can be done when memory is freed and/or at user defined intervals: db_interval. Upon error, file and line number are logged, and abort() is called.

To use, type make tests, and you should see something like:

gcc -g -D_DB_ALLOC_C_ test.c dballoc.o -o test
DB_ALLOC="i=100,f=0" ./test
UNFREED ALLOCATIONS:
Head fence post overwrite, alloced from addr 0x8048900
         Before = 50614468456144ff : PaDhEaD
        After  = 5061446845614401 : PaDhEaD`
        Data   = 00000000000000000000 : 
804a9cc: 10 bytes allocated from addr 0x8048900
gcc -g test.c dballocl.o -o testl
DB_ALLOC="i=100,f=0" ./testl
UNFREED ALLOCATIONS:
Head fence post overwrite, alloced from line 4 in file test.c
         Before = 50614468456144ff : PaDhEaD
        After  = 5061446845614401 : PaDhEaD`
        Data   = 00000000000000000000 : 
804a82c: 10 bytes allocated from line 4 in file test.c
You can then link dballoc.o with your own code. To enable checking, set the env var DB_ALLOC="f=0,i=100"
ie. never fatal and check heap for corruption every 100 calls to dballoc.. Default is zero, which is disabled and so just checks for memory leaks.

Following are the valid option arguments for DB_ALLOC.

d - debugging on (default 0), all other options enable this.
l - logfile to write to (default stderr)
i - interval to check heap for fencepost overwrites (default=0)
k - kill program on error (default=1)
n - ignore free null pointers (default=0)
f - do not actually free memory (default=0)
w - check for writes to freed if 'n' option is on. (default=1)
b - bad pointers are chained to real free/realloc (default=0)
x - set atexit free check routine (default=1)
v - verbose, show all allocations/frees (default=0)
q - quiet, don't show warnings (default=0)
z - fill freed memory with Zfill (default=0)
Z - The Zfill value for above (default=0)
Note: Not setting the DB_ALLOC variable causes the library to do nothing other than chain directly to the malloc, etc lib functions. But after testing is complete, you can recompile your source with -D_DB_ALLOC_C_ to elminate the wrapped call.

Following are the functions/vars you can access from the debugger.

int db_heap_error(void* vp, int head);	/* Set breakpoint, and ret 0 to ignore */
void db_heap_check();		/* Check allocations */
void db_dump_allocs();		/* Dump all allocations */
void db_dump_since(int mark);	/* Dump allocs since mark */
extern int db_interval;		/* Interval to check heap at */
extern int db_mark;		/* Mark/Serial # incremented at each new alloc */
extern int db_kill;		/* Def=1.  rc for db_heap_error() */
extern int db_verbose;		/* See options */
extern int db_quiet;		/* See options */
extern int db_free;		/* Free data */
extern int db_writes;		/* Detect writes to freed data */
extern int db_freebad;		/* free unknown pointers */
extern int db_fillfree;		/* fill freed blocks with const */
extern int db_fillvalue=0;      /* fill with this */
extern int db_checkstart;	/* Start all heap checks from this mark */

In a typical session, you might run from the debugger, and change the db_interval to a low value to detect overwrites.

Compile Options

_DB_BIGPAD_ uses a pad of about 70 chars, instead of the default 8
_DB_ALLOC_C_ user source should ignore include header file dballoc.h
DB_ALLOC_LIB lets library be a dropin replacement for GNU malloc
]