YADM [Yet Another Malloc Debug]
Christos S. Zoulas
christos at theory.TC.Cornell.EDU
Sat Jun 15 03:39:16 AEST 1991
Hello,
Since lots of people have been asking for this kind of library lately,
here's my shot at it. I don't claim it is better than any of the others,
but it is the one that I have been using for a long while, and it works
very well for me. I hope it proves useful to you too.
christos
#! /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: Makefile README debugalloc.c malloc.h tst.c
# Wrapped by christos at guillemin on Fri Jun 14 13:35:44 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(132 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
XSHELL = /bin/sh
XCFLAGS = -O -DDEBUG
X
Xtst: tst.o debugalloc.o
X cc ${CFLAGS} tst.o debugalloc.o -o tst
X
Xclean:
X rm -f *.o tst *.bak
END_OF_FILE
if test 132 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(281 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X
XThis is another debugging malloc library replacement. It is intended mostly
Xto help track down memory leaks, and not memory overwriting. I hope it
Xproves useful to someone.
X
XTo use just include "malloc.h" in your program, compile with -DDEBUG, and
Xlink in debugalloc.o
X
Xchristos
END_OF_FILE
if test 281 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'debugalloc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'debugalloc.c'\"
else
echo shar: Extracting \"'debugalloc.c'\" \(9003 characters\)
sed "s/^X//" >'debugalloc.c' <<'END_OF_FILE'
X/* $Header: /home/hyperion/mu/christos/src/mine/lib/alloc/RCS/debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $ */
X/*
X *
X * debugalloc.c : Special Debug Malloc Routines
X *
X * Routines:
X * char * DebugMalloc();
X * char * DebugCalloc();
X * char * DebugRealloc();
X * void DebugFree();
X * unsigned DebugMemStat();
X * unsigned DebugMemPtr();
X * void DebugMemChain();
X *
X * $Log: debugalloc.c,v $
X * Revision 1.4 1991/05/05 02:49:43 christos
X * Fixed small lint bug
X *
X * Revision 1.3 1991/04/21 00:14:18 christos
X * Fixed free error message
X *
X * Revision 1.2 1991/02/10 00:44:07 christos
X * Added tests for pointers out of the allocated
X * range
X *
X * Revision 1.1 1991/02/01 08:12:55 christos
X * Initial revision
X *
X */
X#ifndef lint
Xstatic char rcsid[] = "$Id: debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $";
X#endif /* lint */
X#include <stdio.h>
X
X#ifdef __STDC__
X# include <stdlib.h>
X# include <memory.h>
X#else
Xextern char *malloc();
Xextern char *calloc();
Xextern char *realloc();
Xextern void free();
Xextern void abort();
Xextern char *memset();
Xextern void exit();
X#endif
X
X#ifndef NIL
X# define NIL(a) ((a *) 0)
X#endif /* NIL */
X
X#ifndef MIN
X# define MIN(a, b) ((a) > (b) ? (b) : (a))
X#endif /* MIN */
X
X#ifndef MAX
X# define MAX(a, b) ((a) < (b) ? (b) : (a))
X#endif /* MAX */
X
X#ifndef private
X# define private static
X#endif /* private */
X
X#ifndef public
X# define public
X#endif /* public */
X
X#define SIG_GOOD 0x01020304
X#define SIG_FREE 0x04030201
X#define SIG_CHAIN 0x44332211
X#define OVERHEAD sizeof(debug_t)
X
X
X#ifdef __STDC__
Xtypedef void *Ptr;
X#else
Xtypedef char *Ptr;
X#endif
X
Xtypedef struct debug_t {
X long d_sign;
X unsigned long d_size;
X char * d_file;
X long d_line;
X union {
X struct {
X struct debug_t *c_prev;
X struct debug_t *c_next;
X } d_c;
X struct {
X char *f_file;
X long f_line;
X } d_f;
X } d_d;
X} debug_t;
X
X#define d_next d_d.d_c.c_next
X#define d_prev d_d.d_c.c_prev
X#define d_ffile d_d.d_f.f_file
X#define d_fline d_d.d_f.f_line
X
X
X
Xprivate unsigned _memused = 0;
Xprivate unsigned _memalloc = 0;
Xprivate Ptr _memtop = (Ptr) 0;
Xprivate Ptr _membot = (Ptr) 0xffffffff;
Xprivate debug_t *chain;
X
X
X/* _chaini():
X * Insert block in chain
X */
Xprivate debug_t *
X_chaini(tptr, n, fname, lineno)
Xchar **tptr;
Xunsigned n;
Xchar *fname;
Xint lineno;
X{
X static debug_t __chain;
X debug_t *dbg;
X
X dbg = (debug_t *) *tptr;
X *tptr += OVERHEAD;
X
X if (chain == NIL(debug_t)) {
X chain = &__chain;
X chain->d_next = chain->d_prev = chain;
X chain->d_sign = SIG_CHAIN;
X chain->d_size = 0;
X chain->d_file = NIL(char);
X chain->d_line = 0;
X }
X dbg->d_sign = SIG_GOOD;
X dbg->d_size = n;
X dbg->d_file = fname;
X dbg->d_line = lineno;
X dbg->d_next = chain->d_next;
X dbg->d_prev = chain;
X chain->d_next->d_prev = dbg;
X chain->d_next = dbg;
X chain = dbg;
X _memused += chain->d_size;
X _memalloc++;
X return(dbg);
X} /* end _chaini */
X
X
X/* _chaina():
X * Allocate a block of the required size
X */
Xprivate Ptr
X_chaina(n, action, routine, fname, lineno, tptr)
Xunsigned n;
Xchar *action;
XPtr (*routine)();
Xchar *fname;
Xint lineno;
XPtr tptr;
X{
X char *ptr;
X debug_t *dbg;
X
X if (tptr != (Ptr) 0 && (tptr < _membot || tptr > _memtop ||
X ((int) tptr) & 0x3)) {
X (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n",
X fname, lineno, action);
X abort();
X }
X if (n == 0) {
X (void) fprintf(stderr,
X "*** %s, %d: %s zero length block.\n",
X fname, lineno, action);
X if (tptr != (Ptr) 0) {
X dbg = (debug_t *) tptr;
X (void) _chaini((char **) &tptr, (unsigned) dbg->d_size,
X dbg->d_file, (int) dbg->d_line);
X }
X abort();
X }
X
X ptr = (tptr == (Ptr) 0) ? (char *) (*routine)(n+OVERHEAD) :
X (*routine)(tptr, n+OVERHEAD);
X
X _memtop = MAX((Ptr) ptr, _memtop);
X _membot = MIN((Ptr) ptr, _membot);
X
X if (ptr == NIL(char)) {
X (void) fprintf(stderr,
X "*** %s, %d: Out of memory in %s (current allocation %u).\n",
X fname, lineno, action, n);
X if (tptr != (Ptr) 0) {
X dbg = (debug_t *) tptr;
X (void) _chaini((char **) &tptr, (unsigned) dbg->d_size,
X dbg->d_file, (int) dbg->d_line);
X }
X abort();
X }
X return((Ptr) ptr);
X} /* end _chaina */
X
X
X/* _chainf():
X * Free block in chain
X */
Xprivate void
X_chainf(dbg, action, fname, lineno)
Xdebug_t *dbg;
Xchar *action;
Xchar *fname;
Xint lineno;
X{
X dbg->d_sign = SIG_FREE;
X if (chain == dbg)
X chain = dbg->d_prev;
X dbg->d_prev->d_next = dbg->d_next;
X dbg->d_next->d_prev = dbg->d_prev;
X dbg->d_ffile = fname;
X dbg->d_fline = lineno;
X _memused -= dbg->d_size;
X _memalloc--;
X} /* end _chainf */
X
X
X/* _chaing():
X * Return the debug header of a chain
X */
Xprivate debug_t *
X_chaing(ptr, action, fname, lineno)
Xchar **ptr;
Xchar *action;
Xchar *fname;
Xint lineno;
X{
X if (*ptr == NIL(char)) {
X (void) fprintf(stderr, "**** %s, %d: %s nil pointer.\n",
X fname, lineno, action);
X abort();
X }
X *ptr -= OVERHEAD;
X if ((Ptr) *ptr < _membot || (Ptr) *ptr > _memtop || (((long) *ptr) & 0x3)) {
X (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n",
X fname, lineno, action);
X abort();
X }
X return((debug_t *) *ptr);
X} /* end _chaing */
X
X
X
X
X/* _chainc():
X * Check block in chain
X */
Xprivate void
X_chainc(dbg, action, fname, lineno)
Xdebug_t *dbg;
Xchar *action;
Xchar *fname;
Xint lineno;
X{
X static char *msg1 = "*** %s, %d: %s %s block";
X static char *msg2 = " [%s, %d: %s]";
X
X switch (dbg->d_sign) {
X case SIG_GOOD:
X break;
X case SIG_FREE:
X (void) fprintf(stderr, msg1, fname, lineno, action, "freed");
X (void) fprintf(stderr, msg2, dbg->d_file, dbg->d_line, "allocated");
X (void) fprintf(stderr, msg2, dbg->d_ffile, dbg->d_fline, "freed");
X abort();
X break;
X default:
X (void) fprintf(stderr, msg1, fname, lineno, action, "invalid");
X (void) fprintf(stderr, ".\n");
X abort();
X break;
X }
X} /* end _chainc */
X
X
X/* DebugMalloc():
X * real alloc
X */
Xpublic Ptr
XDebugMalloc(n, fname, lineno)
Xunsigned n;
Xchar *fname;
Xint lineno;
X{
X static char *routine = "malloc";
X Ptr ptr;
X
X ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
X (void) _chaini((char **) &ptr, n, fname, lineno);
X return(ptr);
X} /* end DebugMalloc */
X
X
X/* DebugFree():
X * free memory counting the number of bytes freed
X */
Xpublic void
XDebugFree(ptr, fname, lineno)
XPtr ptr;
Xchar *fname;
Xint lineno;
X{
X static char *routine = "free";
X debug_t *dbg;
X
X dbg = _chaing((char **) &ptr, routine, fname, lineno);
X _chainc(dbg, routine, fname, lineno);
X _chainf(dbg, routine, fname, lineno);
X free(ptr);
X} /* end DebugFree */
X
X
X/* DebugMemStat():
X * return the amount of memory in use
X */
Xpublic unsigned
XDebugMemStat()
X{
X return(_memused);
X} /* end DebugMemStat */
X
X
X/* DebugMemPtr():
X * return the amount of memory in use
X */
Xpublic unsigned
XDebugMemPtr(ptr, fname, lineno)
XPtr ptr;
Xchar *fname;
Xint lineno;
X{
X static char *routine = "get size";
X debug_t *dbg;
X
X dbg = _chaing((char **) &ptr, routine, fname, lineno);
X _chainc(dbg, routine, fname, lineno);
X
X return((unsigned) dbg->d_size);
X} /* end DebugMemPtr */
X
X
X/* DebugRealloc():
X * real alloc
X */
Xpublic Ptr
XDebugRealloc(ptr, n, fname, lineno)
XPtr ptr;
Xunsigned n;
Xchar *fname;
Xint lineno;
X{
X static char *routine = "realloc";
X debug_t *dbg;
X
X dbg = _chaing((char **) &ptr, routine, fname, lineno);
X _chainc(dbg, routine, fname, lineno);
X _chainf(dbg, routine, fname, lineno);
X ptr = _chaina(n, routine, realloc, fname, lineno, ptr);
X dbg = _chaini((char **) &ptr, n, fname, lineno);
X
X return(ptr);
X} /* end DebugRealloc */
X
X
X/* DebugCalloc():
X * real alloc
X */
Xpublic Ptr
XDebugCalloc(n, sz, fname, lineno)
Xunsigned n, sz;
Xchar *fname;
Xint lineno;
X{
X static char *routine = "calloc";
X Ptr ptr;
X
X n *= sz;
X ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
X (void) _chaini((char **) &ptr, n, fname, lineno);
X memset((char *) ptr, 0, n);
X return(ptr);
X} /* end DebugCalloc */
X
X/* DebugMemChain():
X * Dump the memory chain
X */
Xpublic void
XDebugMemChain()
X{
X debug_t *dbg;
X unsigned min, max;
X
X max = 0x00000000;
X min = 0xffffffff;
X
X if (chain == NIL(debug_t) || chain->d_sign == SIG_CHAIN) {
X (void) fprintf(stdout, "\tNo memory allocated.\n");
X return;
X }
X (void) fprintf(stdout, "\tMemory Allocation Statistics.\n");
X (void) fprintf(stdout, "\t%u bytes allocated in %u chunks.\n",
X _memused, _memalloc);
X for (dbg = chain; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next);
X (void) fprintf(stdout, "\t%8.8s %8.8s %20.20s %5.5s\n",
X "Address", "Size", "Filename", "Line");
X for (dbg = dbg->d_next; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next) {
X (void) fprintf(stdout, "\t%.8x %8d %20.20s %5d\n",
X dbg, dbg->d_size, dbg->d_file, dbg->d_line);
X min = MIN(min, dbg->d_size);
X max = MAX(max, dbg->d_size);
X }
X (void) fprintf(stdout, "\tMin %u Max %u Avg %u.\n",
X min, max, _memused / _memalloc);
X} /* end DebugMemChain */
END_OF_FILE
if test 9003 -ne `wc -c <'debugalloc.c'`; then
echo shar: \"'debugalloc.c'\" unpacked with wrong size!
fi
# end of 'debugalloc.c'
fi
if test -f 'malloc.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'malloc.h'\"
else
echo shar: Extracting \"'malloc.h'\" \(1860 characters\)
sed "s/^X//" >'malloc.h' <<'END_OF_FILE'
X/* $Header$ */
X/*
X * malloc.h: Debugging malloc utils.
X *
X */
X#ifndef _h_malloc
X#define _h_malloc
X
X
X#ifdef __STDC__
X# define P_(a) a
X#else
X# define P_(a) ()
X#endif /* __STDC__ */
X
X#ifdef __STDC__
X# ifndef _MEMALIGN_T
X# define _MEMALIGN_T
X typedef void *memalign_t;
X# endif /* _MEMALIGN_T */
X# ifndef _PTR_T
X# define _PTR_T
X typedef void *ptr_t;
X# endif /* _PTR_T */
X#else /* ! __STDC__ */
X# ifndef _PTR_T
X# define _PTR_T
X typedef char *ptr_t;
X# endif /* _PTR_T */
X# ifdef lint
X /* Fool lint to believe that Malloc returns aligned pointers... */
X# ifndef _MEMALIGN_T
X# define _MEMALIGN_T
X typedef union _memalign_t {
X char a; short b; int c; long d; float e; double f; union _memalign_t *g;
X } *memalign_t;
X# endif /* _MEMALIGN_T */
X# else
X# ifndef _MEMALIGN_T
X# define _MEMALIGN_T
X typedef char *memalign_t;
X# endif /* _MEMALIGN_T */
X# endif /* lint */
X
X#endif /* ! __STDC__ */
X
X/*
X * Memory allocation macros
X */
X#ifdef DEBUG
X# define malloc(a) (ptr_t) DebugMalloc(a, __FILE__, __LINE__)
X# define realloc(a, n) (ptr_t) DebugRealloc(a, n, __FILE__, __LINE__)
X# define calloc(a, n) (ptr_t) DebugCalloc(a, n, __FILE__, __LINE)
X# define free(a) DebugFree(a, __FILE__, __LINE__)
X# define MemPtr(a) DebugMemPtr(a, __FILE__, __LINE__)
X# define MemStat() DebugMemStat()
X# define MemChain() DebugMemChain()
X#else
X# define MemPtr(a)
X# define MemStat()
X# define MemChain()
X#endif /* DEBUG */
X
X#ifdef DEBUG
Xextern memalign_t DebugMalloc P_((unsigned, char *, int));
Xextern memalign_t DebugCalloc P_((unsigned, unsigned, char *, int));
Xextern memalign_t DebugRealloc P_((ptr_t, unsigned, char *, int));
Xextern memalign_t DebugFree P_((ptr_t, char *, int));
Xextern unsigned DebugMemPtr P_((ptr_t, char *, int));
Xextern unsigned DebugMemStat P_((void));
Xextern memalign_t DebugMemChain P_((void));
X#endif
X
X#endif /* _h_malloc */
END_OF_FILE
if test 1860 -ne `wc -c <'malloc.h'`; then
echo shar: \"'malloc.h'\" unpacked with wrong size!
fi
# end of 'malloc.h'
fi
if test -f 'tst.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tst.c'\"
else
echo shar: Extracting \"'tst.c'\" \(2223 characters\)
sed "s/^X//" >'tst.c' <<'END_OF_FILE'
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X
X#ifdef __STDC__
X# include <stdlib.h>
X# include <memory.h>
X#else
Xextern char *malloc();
Xextern char *calloc();
Xextern char *realloc();
Xextern void free();
Xextern void abort();
Xextern char *memset();
Xextern void exit();
X#endif
X
X#include "malloc.h"
X
Xjmp_buf jb;
X
X
Xvoid
Xsigiot()
X{
X signal(SIGIOT, sigiot);
X MemChain();
X longjmp(jb, 1);
X}
X
X
Xmain()
X{
X char *ptr;
X
X signal(SIGIOT, sigiot);
X
X if (!setjmp(jb)) {
X ptr = (char *) malloc(10);
X (void) fprintf(stderr, "1. Malloc 10 ok\n");
X }
X else
X (void) fprintf(stderr, "1. Malloc 10 failed\n");
X
X if (!setjmp(jb)) {
X malloc(0);
X (void) fprintf(stderr, "2. Malloc 0 failed\n");
X }
X else
X (void) fprintf(stderr, "2. Malloc 0 ok\n");
X
X if (!setjmp(jb)) {
X realloc(0, 20);
X (void) fprintf(stderr, "3. Realloc null failed\n");
X }
X else
X (void) fprintf(stderr, "3. Realloc null ok\n");
X
X if (!setjmp(jb)) {
X realloc(ptr, 0);
X (void) fprintf(stderr, "4. Realloc 0 failed\n");
X }
X else
X (void) fprintf(stderr, "4. Realloc 0 ok\n");
X
X if (!setjmp(jb)) {
X ptr = (char *) realloc(ptr, 40);
X (void) fprintf(stderr, "5. Realloc valid ok\n");
X }
X else
X (void) fprintf(stderr, "5. Realloc valid failed\n");
X
X if (!setjmp(jb)) {
X ptr = (char *) realloc(20, 40);
X (void) fprintf(stderr, "6. Realloc invalid failed\n");
X }
X else
X (void) fprintf(stderr, "6. Realloc invalid ok\n");
X
X if (!setjmp(jb)) {
X free(0);
X (void) fprintf(stderr, "7. Free null failed\n");
X }
X else
X (void) fprintf(stderr, "7. Free null ok\n");
X
X if (!setjmp(jb)) {
X free(ptr);
X (void) fprintf(stderr, "8. Free valid ok\n");
X }
X else
X (void) fprintf(stderr, "8. Free valid failed\n");
X
X if (!setjmp(jb)) {
X free(20);
X (void) fprintf(stderr, "9. Free invalid failed\n");
X }
X else
X (void) fprintf(stderr, "9. Free invalid ok\n");
X
X if (!setjmp(jb)) {
X free(ptr);
X (void) fprintf(stderr, "10. Free freed failed\n");
X }
X else
X (void) fprintf(stderr, "10. Free freed ok\n");
X
X if (!setjmp(jb)) {
X realloc(ptr, 20);
X (void) fprintf(stderr, "11. Realloc freed failed\n");
X }
X else
X (void) fprintf(stderr, "11. Realloc freed ok\n");
X exit(0);
X}
X
END_OF_FILE
if test 2223 -ne `wc -c <'tst.c'`; then
echo shar: \"'tst.c'\" unpacked with wrong size!
fi
# end of 'tst.c'
fi
echo shar: End of shell archive.
exit 0
--
Christos Zoulas | 389 Theory Center, Electrical Engineering,
christos at ee.cornell.edu | Cornell University, Ithaca NY 14853.
christos at crnlee.bitnet | Phone: (607) 255 0302, Fax: (607) 255 9072
More information about the Alt.sources
mailing list