Article View: comp.unix.bsd
Article #6089Re: debugging malloc for pyramid
From: Paul A Vixie
Date: Sat, 09 May 1992 22:59
Date: Sat, 09 May 1992 22:59
408 lines
11161 bytes
11161 bytes
>> I am looking for a malloc library with debugging
>> features that will run on a pyramid in the UCB
>> universe. Please mail reply's.
The reply is useful to the general audience, so I'll post it and then
mail you a copy of this article.
What kind of debugging are you hoping to do? If you're looking for a
malloc that catches data overruns, the one in BSD and Perl has that
feature but the libcc.a version usually ifdef's out the debug code for
performance reasons.
If you want one that detects overruns AND UNDERRUNS, there's a GNU
malloc available but it is labelled "beta test - real release soon"
and yet is inexplicably several years old.
If you want one that will trace your allocations and deallocations
(useful for finding memory leaks), please find it below. this has
not been released to comp.sources.unix yet since i'm lazy...
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: README Makefile dmalloc.c dmalloc.h dmt.c
# Wrapped by vixie@cognition.pa.dec.com on Sat May 9 22:58:32 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1183 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
dmalloc - debugging wrapper around malloc(3)
paul vixie (@decwrl) 9 may 1992 [released]
X
normal usage is an enabling macro called DMALLOC (either -DMALLOC in your
Makefile, or "#define DMALLOC" in *all* your .c files (or some .h file
included in all your .c files). then, in each c (or in the "big" .h):
X
X#ifdef DMALLOC
X#include "dmalloc.h"
X#else
char *malloc(), *calloc(), *realloc();
void free();
X#endif
X
look at (and build, and run) dmt.c to see what it does, which is sortof:
X
X% make dmt
gcc -O -c dmt.c
gcc -O -c dmalloc.c
gcc -o dmt dmt.o dmalloc.o
X% cat dmt.c
X#include <stdio.h>
X#include "dmalloc.h"
X
main() {
X char *m1 = malloc(41);
X char *m2 = malloc(52);
X char *m3 = malloc(63);
X
X dmallocstats(stdout);
X free(m2);
X dmallocstats(stdout);
X}
X% ./dmt
dallocstats [ private mem used=3172, avail=62364 ]
X "dmt.c":7 calls=1 blocks=1 bytes=63
X "dmt.c":6 calls=1 blocks=1 bytes=52
X "dmt.c":5 calls=1 blocks=1 bytes=41
dallocstats [ private mem used=4224, avail=61312 ]
X "dmt.c":7 calls=1 blocks=1 bytes=63
X "dmt.c":6 calls=1
X "dmt.c":10 calls=1
X "dmt.c":5 calls=1 blocks=1 bytes=41
END_OF_FILE
if test 1183 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(120 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
CC=gcc
X
all: dmalloc.o
X
dmt: dmt.o dmalloc.o
X $(CC) -o dmt dmt.o dmalloc.o
X
clean:
X rm -f *.o *~ *.BAK *.CKP
X rm -f dmt
END_OF_FILE
if test 120 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'dmalloc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dmalloc.c'\"
else
echo shar: Extracting \"'dmalloc.c'\" \(4808 characters\)
sed "s/^X//" >'dmalloc.c' <<'END_OF_FILE'
X/* dmalloc - debugging layer on top of malloc
X * vix 25mar92 [fixed bug in round-up calcs in alloc()]
X * vix 24mar92 [added size calcs, improved printout]
X * vix 22mar92 [written]
X */
X
X#include <stdio.h>
X#include <signal.h>
X
X#define TRUE 1
X#define FALSE 0
typedef unsigned bool;
X
X#define MAX_MEMORY 65536 /* must fit in typeof(datum.size) */
X#define MAX_CALLERS 256 /* must be **2 */
X
typedef struct caller {
X struct caller *next;
X struct filenam *file;
X struct calltab *frees;
X unsigned line;
X unsigned calls;
X unsigned blocks;
X unsigned bytes;
X} caller;
X
typedef struct filenam {
X struct filenam *next;
X char *name;
X} filenam;
X
typedef struct calltab {
X struct caller *callers[MAX_CALLERS];
X} calltab;
X
typedef struct datum {
X unsigned size; /* size of malloc'd item */
X unsigned caller; /* offset into memory[] */
X /* user data follows */
X} datum;
X
static char memory[MAX_MEMORY];
static char *nextmem = memory;
static char *alloc(size) unsigned size; {
X char *thismem = nextmem;
X int oddness = (size % sizeof(char*));
X if (oddness)
X size += (sizeof(char*) - oddness);
X nextmem += size;
X if (nextmem >= &memory[MAX_MEMORY]) {
X fprintf(stderr, "dmalloc.alloc: out of mem\n");
X kill(0, SIGBUS);
X }
X return thismem;
X }
X
static filenam *Files;
static calltab Callers;
X
X/*--------------------------------------------------- imports
X */
X
char *malloc(), *calloc(), *realloc();
void free();
X
X/*--------------------------------------------------- private
X */
X
X#define STR_EQ(l,r) (((l)[0] == (r)[0]) && !strcmp(l, r))
X
static filenam *
findFile(file, addflag)
X char *file;
X bool addflag;
X{
X filenam *f;
X
X for (f = Files; f; f = f->next)
X if (STR_EQ(file, f->name))
X return f;
X if (!addflag)
X return NULL;
X f = (filenam*) alloc(sizeof(filenam));
X f->next = Files;
X Files = f;
X f->name = alloc(strlen(file) + 1);
X strcpy(f->name, file);
X return f;
X}
X
static caller *
findCaller(ctab, file, line, addflag)
X calltab *ctab;
X char *file;
X unsigned line;
X bool addflag;
X{
X unsigned hash = line & (MAX_CALLERS - 1);
X caller *c;
X
X for (c = ctab->callers[hash]; c; c = c->next)
X if ((c->line == line) && STR_EQ(c->file->name, file))
X return c;
X if (!addflag)
X return NULL;
X c = (caller*) alloc(sizeof(caller));
X c->next = ctab->callers[hash];
X c->file = findFile(file, TRUE);
X c->line = line;
X c->calls = 0;
X c->frees = (calltab *) alloc(sizeof(calltab));
X ctab->callers[hash] = c;
X return c;
X}
X
X/*--------------------------------------------------- public
X */
X
char *
dmalloc(file, line, size)
X char *file;
X unsigned line;
X unsigned size;
X{
X caller *c;
X datum *d;
X
X c = findCaller(&Callers, file, line, TRUE);
X d = (datum *) malloc(sizeof(datum) + size);
X d->size = size;
X d->caller = ((char *)c) - memory;
X c->calls++;
X c->blocks++;
X c->bytes += size;
X return (char *) (d+1);
X}
X
void
dfree(file, line, ptr)
X char *file;
X unsigned line;
X char *ptr;
X{
X caller *c, *a;
X datum *d;
X
X d = (datum *) ptr; d--;
X a = (caller *) (memory + d->caller);
X a->bytes -= d->size;
X a->blocks--;
X c = findCaller(a->frees, file, line, TRUE);
X c->calls++;
X free((char*) d);
X}
X
char *
dcalloc(file, line, nelems, elsize)
X char *file;
X unsigned line;
X unsigned nelems, elsize;
X{
X unsigned size = (nelems * elsize);
X char *ptr;
X
X ptr = dmalloc(file, line, size);
X bzero(ptr, size);
X return ptr;
X}
X
char *
drealloc(file, line, ptr, size)
X char *file;
X unsigned line;
X char *ptr;
X unsigned size;
X{
X caller *c, *a;
X datum *d;
X
X d = (datum *) ptr; d--;
X /* fix up stats from allocation */
X a = (caller *) (memory + d->caller);
X a->bytes -= d->size;
X a->blocks--;
X /* we are a "freer" of this allocation */
X c = findCaller(a->frees, file, line, TRUE);
X c->calls++;
X /* get new allocation and stat it */
X c = findCaller(&Callers, file, line, TRUE);
X d = (datum *) realloc((char *) d, sizeof(datum) + size);
X d->size = size;
X d->caller = ((char *)c) - memory;
X c->calls++;
X c->blocks++;
X c->bytes += size;
X return (char *) (d+1);
X}
X
static void
dmalloccallers(outf, prefix, ctab)
X FILE *outf;
X char *prefix;
X calltab *ctab;
X{
X /* this bizarre logic is to print all of a file's entries together */
X filenam *f;
X
X for (f = Files; f; f = f->next) {
X int i;
X
X for (i = MAX_CALLERS-1; i >= 0; i--) {
X caller *c;
X
X for (c = ctab->callers[i]; c; c = c->next) {
X if (f != c->file)
X continue;
X fprintf(outf, "%s\"%s\":%u calls=%u",
X prefix, c->file->name, c->line,
X c->calls);
X if (c->blocks || c->bytes)
X fprintf(outf, " blocks=%u bytes=%u",
X c->blocks, c->bytes);
X fputc('\n', outf);
X if (c->frees)
X dmalloccallers(outf,
X "\t\t", c->frees);
X }
X }
X }
X}
X
void
dmallocstats(outf)
X FILE *outf;
X{
X fprintf(outf, "dallocstats [ private mem used=%u, avail=%u ]\n",
X nextmem - memory, &memory[MAX_MEMORY] - nextmem);
X dmalloccallers(outf, "\t", &Callers);
X}
END_OF_FILE
if test 4808 -ne `wc -c <'dmalloc.c'`; then
echo shar: \"'dmalloc.c'\" unpacked with wrong size!
fi
# end of 'dmalloc.c'
fi
if test -f 'dmalloc.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dmalloc.h'\"
else
echo shar: Extracting \"'dmalloc.h'\" \(356 characters\)
sed "s/^X//" >'dmalloc.h' <<'END_OF_FILE'
X/* dmalloc - debugging layer on top of malloc
X * vix 22mar92 [written]
X */
X
X#define malloc(s) dmalloc(__FILE__, __LINE__, s)
X#define free(p) dfree(__FILE__, __LINE__, p)
X#define calloc(n, s) dcalloc(__FILE__, __LINE__, n, s)
X#define realloc(p, s) drealloc(__FILE__, __LINE__, p, s)
X
char *dmalloc(), *dcalloc(), *drealloc();
void dfree(), dmallocstats();
END_OF_FILE
if test 356 -ne `wc -c <'dmalloc.h'`; then
echo shar: \"'dmalloc.h'\" unpacked with wrong size!
fi
# end of 'dmalloc.h'
fi
if test -f 'dmt.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dmt.c'\"
else
echo shar: Extracting \"'dmt.c'\" \(182 characters\)
sed "s/^X//" >'dmt.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include "dmalloc.h"
X
main() {
X char *m1 = malloc(41);
X char *m2 = malloc(52);
X char *m3 = malloc(63);
X
X dmallocstats(stdout);
X free(m2);
X dmallocstats(stdout);
X}
END_OF_FILE
if test 182 -ne `wc -c <'dmt.c'`; then
echo shar: \"'dmt.c'\" unpacked with wrong size!
fi
# end of 'dmt.c'
fi
echo shar: End of shell archive.
exit 0
--
Paul Vixie, DEC Network Systems Lab
Palo Alto, California, USA "Ready, Fire, Aim"
<vixie@pa.dec.com> decwrl!vixie
<paul@vix.com> vixie!paul alt.pink.bunny.boom.boom.boom moderator
Technical Details
Message-ID:
<VIXIE.92May9225910@cognition.pa.dec.com>Path:
arc1-ca.pugleaf.net!wupost!darwin.sura.net!haven.umd.edu!decuac!pa.dec.com!vixieReferences:
<1992May8.195717.15600@baarsa.bell-atl.com>Show Full Headers
Complete Article Headers
Newsgroups: comp.unix.bsd,alt.sources Path: arc1-ca.pugleaf.net!wupost!darwin.sura.net!haven.umd.edu!decuac!pa.dec.com!vixie From: vixie@pa.dec.com (Paul A Vixie) Subject: Re: debugging malloc for pyramid In-Reply-To: dd6kdn0@baarsa.bell-atl.com's message of 8 May 92 19:57:17 GMT Message-ID: <VIXIE.92May9225910@cognition.pa.dec.com> Sender: news@PA.dec.com (News) Organization: DEC Network Software Lab References: <1992May8.195717.15600@baarsa.bell-atl.com> Date: 9 May 92 22:59:10 Lines: 408