MALLOC(3)

NAME
mallocMagic, freeMagic - a new memory allocator in libmagicutils.a

SYNOPSIS
#include magic.h
#include malloc.h

char *mallocMagic(size)
unsigned size;

char *callocMagic(size)
unsigned size;

MALLOC(type_decl, var, size)
type_decl var;
unsigned size;

CALLOC(type_decl, var, size)
type_decl var;
unsigned size;

freeMagic(var)
char *var;

FREE(var)
char *var;

cc -DMALLOCTRACE ... ~cad/src/magic/lib/libmagictrace.a

mallocTraceInit(filename)
char *filename;

mallocTraceEnable()

mallocTraceDisable()

mallocTraceDone()

mallocTraceOnlyWatched(only)
bool only;

bool mallocTraceWatch(addr)
char *addr;

bool mallocTraceUnWatch(addr)
char *addr;

DESCRIPTION
These procedures implement a new memory allocator. They provide fast allocation and freeing for programs that allocate thousands or millions of objects of similar sizes. Speed results from maintaining separate free-lists for objects of each size, providing fast macros MALLOC and FREE for doing allocation and freeing, and clustering objects of the same size on the same page in an attempt to improve locality of reference. In addition, these procedures provide features to aid in the debugging of programs that do a lot of memory allocation and freeing; used in conjunction with prleak(8) they can detect storage leaks and also duplicate attempts to free the same storage location.

Memory is allocated using either the procedure mallocMagic or the macro MALLOC. The former has an interface identical to that of the standard UNIX library procedure malloc(3), namely, it returns a pointer to a region of memory sufficiently large to hold size bytes. The macro MALLOC is noticeably faster, particularly on machines with brain-dead procedure calls (such as a certain popular machine made by the second largest U.S. computer manufacturer). Its usage is a bit unusual, in that its first argument is a type specification and its second is modified in place. For example, to allocate an object of type HashEntry * that is 20 bytes long, and to assign this to the pointer he, one could write:

MALLOC(HashEntry *, he, 20);

Note that there are no parentheses around the HashEntry * above. After executing this macro, he would point to a HashEntry that was 20 bytes long.

The macro CALLOC and the procedure callocMagic perform function analagous to MALLOC and mallocMagic except that the malloc'd memory is zeroed.

Memory can be freed using either the procedure freeMagic, which frees its argument var exactly as does the UNIX free(3), or using the FREE macro, which does the same thing to var but is faster.

Users of MALLOC and FREE should beware that they are macros that include C statements enclosed in a pair of braces ({ ... }), and should be treated accordingly. For example, it is not legal to type:

if (i != j)
	MALLOC(HashEntry *, he, i);
else
	return (NULL);
One should instead use:

if (i != j)
{
	MALLOC(HashEntry *, he, i);
}
else
	return (NULL);

If you wish to take advantage of the debugging features of this memory allocator, you must do two things. First, compile all of your .c files that #include ``malloc.h'' with the -DMALLOCTRACE flag. Second, when you link your program to build an a.out file, use the library ~cad/src/magic/lib/libmagictrace.a instead of the normal libmagicutils.a. The libmagictrace.a library contains additional code to maintain the information needed by the debugging procedures below. If you link your program with the standard library, it will link successfully, but the debugging procedures won't do anything.

The debugging procedures produce a trace file for subsequent analysis by prleak(8). Before any memory is allocated, you should call mallocTraceInit to create the trace file name. Tracing won't actually begin, however, until you call mallocTraceEnable. From that point until mallocTraceDisable, all calls to mallocMagic or freeMagic (or their corresponding macro versions MALLOC and FREE) will be logged to the trace file. Calls to mallocTraceDisable and mallocTraceEnable may be nested; only the outermost mallocTraceEnable has any effect.

If more selective tracing is desired, you can specify that trace information is to be output only for certain addresses. Calling mallocTraceOnlyWatched with only equal to TRUE causes this to happen. An address addr is added to the list of addresses to trace by calling mallocTraceWatch, or removed from this list by calling mallocTraceUnWatch. When mallocTraceOnlyWatched is called with only equal to FALSE, operation reverts to the normal mode of tracing all addresses.

When you are finished with all memory allocation tracing and want to flush all results out to the trace file, call mallocTraceDone. Subsequent calls to the memory allocator will not be traced.

BUGS
The MALLOC and FREE macros are syntactically clumsy, but unfortunately some C optimizers have trouble with syntactically cleaner forms.

The ability to trace specific addresses is only useful if you know which ones to watch. A more generally useful facility would probably be to watch certain sizes of objects, or to allow the user to supply a procedure that could determine whether or not an address was to be traced.

SEE ALSO
magicutils(3)