v19i026: dmake - dmake version 3.7, Part05/37
Dennis Vadura
dvadura at watdragon.waterloo.edu
Fri May 10 05:27:28 AEST 1991
Submitted-by: Dennis Vadura <dvadura at watdragon.waterloo.edu>
Posting-number: Volume 19, Issue 26
Archive-name: dmake/part05
Supersedes: dmake-3.6: Volume 15, Issue 52-77
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is dmake.shar.05 (part 5 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file dmake/dbug/malloc/debug.h continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 5; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test -f _shar_wnt_.tmp; then
sed 's/^X//' << 'SHAR_EOF' >> 'dmake/dbug/malloc/debug.h' &&
X
#define DEBUG0(val,s)
#define DEBUG1(val,s,a1)
#define DEBUG2(val,s,a1,a2)
#define DEBUG3(val,s,a1,a2,a3)
#define DEBUG4(val,s,a1,a2,a3,a4)
#define DEBUG5(val,s,a1,a2,a3,a4,a5)
X
#endif /* DEBUG */
X
X
/*
X * $Log: debug.h,v $
X * Revision 1.2 90/05/11 00:13:08 cpcahil
X * added copyright statment
X *
X * Revision 1.1 90/02/23 07:09:01 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/debug.h ||
echo 'restore of dmake/dbug/malloc/debug.h failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/debug.h'`"
test 2628 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/debug.h: original size 2628, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/dump.c ==============
if test -f 'dmake/dbug/malloc/dump.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/dump.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/dump.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include "malloc.h"
#include "tostring.h"
X
/*
X * Function: malloc_dump()
X *
X * Purpose: to dump a printed copy of the malloc chain and
X * associated data elements
X *
X * Arguments: fd - file descriptor to write data to
X *
X * Returns: nothing of any use
X *
X * Narrative: Just print out all the junk
X *
X * Notes: This function is implemented using low level calls because
X * of the likelyhood that the malloc tree is damaged when it
X * is called. (Lots of things in the c library use malloc and
X * we don't want to get into a catch-22).
X *
X */
X
#ifndef lint
static
char rcs_hdr[] = "$Id: dump.c,v 1.5 90/08/29 21:22:37 cpcahil Exp $";
#endif
X
X
#define ERRSTR "I/O Error on malloc dump file descriptor\n"
X
#define WRITEOUT(fd,str,len) if( write(fd,str,(unsigned)len) != len ) \
X { \
X (void) write(2,ERRSTR,\
X (unsigned)strlen(ERRSTR));\
X exit(120); \
X }
X
void
malloc_dump(fd)
X int fd;
{
X char buffer[512];
X void exit();
X int i;
X extern char * malloc_data_end;
X extern char * malloc_data_start;
X extern struct mlist * malloc_end;
X extern struct mlist malloc_start;
X struct mlist * ptr;
X
X WRITEOUT(fd,"MALLOC CHAIN:\n",14);
X WRITEOUT(fd,"-------------------- START ----------------\n",44);
X
X for(i=0; i < 80; i++)
X {
X buffer[i] = ' ';
X }
X
X for(ptr = &malloc_start; ptr; ptr = ptr->next)
X {
X (void) tostring(buffer, (int)ptr, 8, B_HEX, '0');
X (void) tostring(buffer+9, (int)ptr->next, 8, B_HEX, '0');
X (void) tostring(buffer+18, (int)ptr->prev, 8, B_HEX, '0');
X (void) tostring(buffer+27, (int)ptr->flag, 10, B_HEX, '0');
X (void) tostring(buffer+38, (int)ptr->s.size, 8, B_DEC, ' ');
X (void) tostring(buffer+47, (int)ptr->s.size, 8, B_HEX, '0');
X (void) tostring(buffer+57, (int)ptr->data, 8, B_HEX, '0');
X buffer[46] = '(';
X buffer[55] = ')';
X buffer[65] = '\n';
X WRITEOUT(fd,buffer,66);
X }
X WRITEOUT(fd,"-------------------- DONE -----------------\n",44);
X
X WRITEOUT(fd,"Malloc start: ",19);
X (void) tostring(buffer, (int) &malloc_start, 8, B_HEX, '0');
X buffer[8] = '\n';
X WRITEOUT(fd,buffer,9);
X
X WRITEOUT(fd,"Malloc end: ", 19);
X (void) tostring(buffer, (int) malloc_end, 8, B_HEX, '0');
X buffer[8] = '\n';
X WRITEOUT(fd,buffer,9);
X
X WRITEOUT(fd,"Malloc data start: ", 19);
X (void) tostring(buffer, (int) malloc_data_start, 8, B_HEX, '0');
X buffer[8] = '\n';
X WRITEOUT(fd,buffer,9);
X
X WRITEOUT(fd,"Malloc data end: ", 19);
X (void) tostring(buffer, (int) malloc_data_end, 8, B_HEX, '0');
X buffer[8] = '\n';
X WRITEOUT(fd,buffer,9);
X
} /* malloc_dump(... */
X
X
/*
X * $Log: dump.c,v $
X * Revision 1.5 90/08/29 21:22:37 cpcahil
X * miscellaneous lint fixes
X *
X * Revision 1.4 90/05/11 00:13:08 cpcahil
X * added copyright statment
X *
X * Revision 1.3 90/02/24 21:50:07 cpcahil
X * lots of lint fixes
X *
X * Revision 1.2 90/02/24 17:27:48 cpcahil
X * changed $header to $Id to remove full path from rcs id string
X *
X * Revision 1.1 90/02/22 23:17:43 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/dump.c ||
echo 'restore of dmake/dbug/malloc/dump.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/dump.c'`"
test 3179 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/dump.c: original size 3179, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/free.c ==============
if test -f 'dmake/dbug/malloc/free.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/free.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/free.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include "malloc.h"
#include "debug.h"
X
/*
X * Function: free()
X *
X * Purpose: to deallocate malloced data
X *
X * Arguments: ptr - pointer to data area to deallocate
X *
X * Returns: nothing of any value
X *
X * Narrative:
X * verify pointer is within malloc region
X * get mlist pointer from passed address
X * verify magic number
X * verify inuse flag
X * verify pointer connections with surrounding segments
X * turn off inuse flag
X * verify no data overrun into non-malloced area at end of segment
X * IF possible join segment with next segment
X * IF possible join segment with previous segment
X * Clear all data in segment (to make sure it isn't reused)
X *
X */
#ifndef lint
static
char rcs_hdr[] = "$Id: free.c,v 1.9 90/08/29 21:22:48 cpcahil Exp $";
#endif
X
void
free(cptr)
X char * cptr;
{
X char * func = "free";
X int i;
X extern int malloc_checking;
X extern struct mlist * malloc_end;
X extern int malloc_errno;
X extern char * malloc_data_end;
X extern char * malloc_data_start;
X void malloc_join();
X void malloc_memset();
X struct mlist * oldptr;
X struct mlist * ptr;
X
X /*
X * IF malloc chain checking is on, go do it.
X */
X if( malloc_checking )
X {
X (void) malloc_chain_check(1);
X }
X
X /*
X * verify that cptr is within the malloc region...
X */
X if( cptr < malloc_data_start || cptr > malloc_data_end )
X {
X malloc_errno = M_CODE_BAD_PTR;
X malloc_warning(func);
X return;
X }
X
X /*
X * convert pointer to mlist struct pointer. To do this we must
X * move the pointer backwards the correct number of bytes...
X */
X
X ptr = (struct mlist *) (cptr - M_SIZE);
X
X if( (ptr->flag&M_MAGIC) != M_MAGIC )
X {
X malloc_errno = M_CODE_BAD_MAGIC;
X malloc_warning(func);
X return;
X }
X
X if( ! (ptr->flag & M_INUSE) )
X {
X malloc_errno = M_CODE_NOT_INUSE;
X malloc_warning(func);
X return;
X }
X
X if( (ptr->prev && (ptr->prev->next != ptr) ) ||
X (ptr->next && (ptr->next->prev != ptr) ) ||
X ((ptr->next == NULL) && (ptr->prev == NULL)) )
X {
X malloc_errno = M_CODE_BAD_CONNECT;
X malloc_warning(func);
X return;
X }
X
X ptr->flag &= ~M_INUSE;
X
X /*
X * verify that the user did not overrun the requested number of bytes.
X */
X for(i=ptr->r_size; i < ptr->s.size; i++)
X {
X if( ptr->data[i] != M_FILL )
X {
X malloc_errno = M_CODE_OVERRUN;
X malloc_warning(func);
X break;
X }
X }
X
X DEBUG3(10,"pointers: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
X ptr->prev, ptr, ptr->next);
X
X DEBUG3(10,"size: prev: %9d, ptr: %9d, next: %9d",
X ptr->prev->s.size, ptr->s.size, ptr->next->s.size);
X
X DEBUG3(10,"flags: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
X ptr->prev->flag, ptr->flag, ptr->next->flag);
X
X /*
X * check to see if this block can be combined with the next and/or
X * previous block. Since it may be joined with the previous block
X * we will save a pointer to the previous block and test to verify
X * if it is joined (it's next ptr will no longer point to ptr).
X */
X malloc_join(ptr,ptr->next,0,0);
X
X oldptr = ptr->prev;
X
X malloc_join(ptr->prev, ptr,0,0);
X
X if( oldptr->next != ptr )
X {
X DEBUG0(10,"Oldptr was changed");
X ptr = oldptr;
X }
X
X /*
X * fill this block with '\02's to ensure that nobody is using a
X * pointer to already freed data...
X */
X malloc_memset(ptr->data,M_FREE_FILL,(int)ptr->s.size);
X
}
X
/*
X * $Log: free.c,v $
X * Revision 1.9 90/08/29 21:22:48 cpcahil
X * miscellaneous lint fixes
X *
X * Revision 1.8 90/05/11 00:13:08 cpcahil
X * added copyright statment
X *
X * Revision 1.7 90/02/25 11:00:18 cpcahil
X * added support for malloc chain checking.
X *
X * Revision 1.6 90/02/24 21:50:18 cpcahil
X * lots of lint fixes
X *
X * Revision 1.5 90/02/24 17:29:13 cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs
X * id string
X *
X * Revision 1.4 90/02/24 15:15:32 cpcahil
X * 1. changed ALREADY_FREE errno to NOT_INUSE so that the same errno could
X * be used by both free and realloc (since it was the same error).
X * 2. fixed coding bug
X *
X * Revision 1.3 90/02/24 14:23:45 cpcahil
X * fixed malloc_warning calls
X *
X * Revision 1.2 90/02/24 13:59:10 cpcahil
X * added function header.
X * Modified calls to malloc_warning/malloc_fatal to use new code error messages
X * Added support for malloc_errno setting of error codes.
X *
X * Revision 1.1 90/02/22 23:17:43 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/free.c ||
echo 'restore of dmake/dbug/malloc/free.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/free.c'`"
test 4513 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/free.c: original size 4513, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/m_init.c ==============
if test -f 'dmake/dbug/malloc/m_init.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/m_init.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/m_init.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include "malloc.h"
X
/*
X * Function: malloc_init()
X *
X * Purpose: to initialize the pointers and variables use by the
X * malloc() debugging library
X *
X * Arguments: none
X *
X * Returns: nothing of any value
X *
X * Narrative: Just initialize all the needed variables. Use mallopt
X * to set options taken from the environment.
X *
X */
#ifndef lint
static
char rcs_hdr[] = "$Id: m_init.c,v 1.6 90/08/29 22:23:21 cpcahil Exp $";
#endif
X
void
malloc_init()
{
X char * cptr;
X char * getenv();
X union malloptarg m;
X extern char * malloc_data_end;
X extern char * malloc_data_start;
X extern struct mlist * malloc_end;
X extern struct mlist malloc_start;
X char * sbrk();
X
X /*
X * If already initialized...
X */
X if( malloc_data_start != (char *) 0)
X {
X return;
X }
X
X
X malloc_data_start = sbrk(0);
X malloc_data_end = malloc_data_start;
X malloc_start.s.size = 0;
X malloc_end = &malloc_start;
X
X if( (cptr=getenv("MALLOC_WARN")) != NULL )
X {
X m.i = atoi(cptr);
X (void) mallopt(MALLOC_WARN,m);
X }
X
X if( (cptr=getenv("MALLOC_FATAL")) != NULL)
X {
X m.i = atoi(cptr);
X (void) mallopt(MALLOC_FATAL,m);
X }
X
X if( (cptr=getenv("MALLOC_CKCHAIN")) != NULL)
X {
X m.i = atoi(cptr);
X (void) mallopt(MALLOC_CKCHAIN,m);
X }
X
X if( (cptr=getenv("MALLOC_ERRFILE")) != NULL)
X {
X m.str = cptr;
X (void) mallopt(MALLOC_ERRFILE,m);
X }
X
}
X
/*
X * $Log: m_init.c,v $
X * Revision 1.6 90/08/29 22:23:21 cpcahil
X * fixed mallopt to use a union as an argument.
X *
X * Revision 1.5 90/08/29 21:22:50 cpcahil
X * miscellaneous lint fixes
X *
X * Revision 1.4 90/05/11 15:53:35 cpcahil
X * fixed bug in initialization code.
X *
X * Revision 1.3 90/05/11 00:13:08 cpcahil
X * added copyright statment
X *
X * Revision 1.2 90/02/24 21:50:20 cpcahil
X * lots of lint fixes
X *
X * Revision 1.1 90/02/24 17:10:53 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/m_init.c ||
echo 'restore of dmake/dbug/malloc/m_init.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/m_init.c'`"
test 2022 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/m_init.c: original size 2022, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/m_perror.c ==============
if test -f 'dmake/dbug/malloc/m_perror.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/m_perror.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/m_perror.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X
#ifndef lint
static
char rcsid[] = "$Id: m_perror.c,v 1.5 90/08/29 21:25:08 cpcahil Exp $";
#endif
X
/*
X * malloc errno error strings...
X */
X
char *malloc_err_strings[] =
{
X "No errors",
X "Malloc chain is corrupted, pointers out of order",
X "Malloc chain is corrupted, end before end pointer",
X "Pointer is not within malloc area",
X "Malloc region does not have valid magic number in header",
X "Pointers between this segment and ajoining segments are invalid",
X "Data has overrun beyond requested number of bytes",
X "Data in free'd area has been modified",
X "Data are is not in use (can't be freed or realloced)",
X "Unable to get additional memory from the system",
X "Pointer within malloc region, but outside of malloc data bounds",
X (char *) 0
};
X
/*
X * Function: malloc_perror()
X *
X * Purpose: to print malloc_errno error message
X *
X * Arguments: str - string to print with error message
X *
X * Returns: nothing of any value
X *
X * Narrative:
X */
void
malloc_perror(str)
X char * str;
{
X extern int malloc_errno;
X register char * s;
X register char * t;
X
X if( str && *str)
X {
X for(s=str; *s; s++)
X {
X /* do nothing */;
X }
X
X (void) write(2,str,(unsigned)(s-str));
X (void) write(2,": ",(unsigned)2);
X }
X
X t = malloc_err_strings[malloc_errno];
X
X for(s=t; *s; s++)
X {
X /* do nothing */;
X }
X
X (void) write(2,t,(unsigned)(s-t));
X
X (void) write(2,"\n",(unsigned)1);
}
X
/*
X * $Log: m_perror.c,v $
X * Revision 1.5 90/08/29 21:25:08 cpcahil
X * added additional error message that was missing (and
X * caused a core dump)
X *
X * Revision 1.4 90/05/11 00:13:08 cpcahil
X * added copyright statment
X *
X * Revision 1.3 90/02/24 21:50:21 cpcahil
X * lots of lint fixes
X *
X * Revision 1.2 90/02/24 17:39:55 cpcahil
X * 1. added function header
X * 2. added rcs id and log strings.
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/m_perror.c ||
echo 'restore of dmake/dbug/malloc/m_perror.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/m_perror.c'`"
test 1973 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/m_perror.c: original size 1973, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/malloc.3 ==============
if test -f 'dmake/dbug/malloc/malloc.3' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/malloc.3 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/malloc.3' &&
.TH MALLOC 3 "" "" "1.0"
.ds ]T
.\"/*
.\" * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
.\" * You may copy, distribute, and use this software as long as this
.\" * copyright statement is not removed.
.\" */
.\" $Id: malloc.3,v 1.3 90/08/29 22:24:44 cpcahil Exp $
.SH NAME
malloc \t- debugging malloc library
.SH SYNOPSIS
.ft B
.nf
#include <malloc.h>
X
char * calloc(nelem,elsize);
void free(ptr);
char * malloc(size);
int malloc_chain_check(flag);
void malloc_dump(fd);
int mallopt(cmd,val)
char * realloc(ptr,size);
X
int cmd,fd,flag;
unsigned elsize,nelem,size;
char * ptr;
union malloptarg val;
X
.fi
.ft R
.SH DESCRIPTION
This malloc library is a replacement for the standard library to be used
during software development/debugging. See the standard malloc(3) pages
for more information on the use of the following functions:
.nf
.in +.5i
calloc(), free(), malloc(), realloc()
.in -.5i
.fi
.sp
This library differs from the standard malloc library in the
following ways:
.P
1. Each malloc segment contains a magic number so that free can
verify that the pointer passed points to a valid malloc segment.
.P
2. Each malloc segment is filled with a non-zero pattern so that code that
depends upon malloc segments being null will fail.
.P
3. The size of each segment will be at least 1 byte larger than requested
and the extra bytes will be filled with a non-zero pattern. When free is
called, it will verify that you did not go beyond the number of bytes
you asked for.
.P
4. When a segment is freed, it will be filled with a different non-zero pattern
to ensure that the program doesn't depend upon the use of already freed data.
.P
5. Whenever any of the string or memory functions (str*, b*, mem*) are
called with a pointer that is within the malloc arena, the operation is
checked to verify that it does not overrun the malloced segment. A failure
of this check is considered a "warning level error" (described later) and
is handled accordingly.
.P
7. Run time checking can include verification of the malloc chain at each
and every call to one of the malloc functions or manually by calling the
malloc_chain_check function.
.P
6. When a problem is found, the action taken is specified at runtime by
environment variables or at compile time by the use of the mallopt()
function.
.P
There are two arbitrary levels of errors, warning and fatal, that this
library will detect. They are broken down as follows:
.P
.nf
.in +.25i
Warning messages include:
.sp
.in +.5i
.ti -.25i
Calling free with a bad pointer
.br
.ti -.25i
Calling a bstring/string/memory (3) function which will go beyond
the end of a malloc block. Note that the library function is
not modified to refuse the operation.
.sp
.in -.5i
Fatal errors are:
.in +.5i
.ti -.25i
Detectable corruption to the malloc chain.
.in -.5i
.in -.25i
.P
The error handling for each level (warning or fatal) are specified using
environment variables or mallopt(). The coding for the error handling is
as follows:
.sp
.nf
.in +.5i
.ti -.25i
X 0 - continue operations
.ti -.25i
X 1 - drop core and exit
.ti -.25i
X 2 - just exit
.ti -.25i
X 3 - drop core, but continue executing. Core files will
be placed into core.[PID].[counter] i.e: core.00123.001
.ti -.25i
128 - dump malloc chain and continue
.ti -.25i
129 - dump malloc chain, dump core, and exit
.ti -.25i
130 - dump malloc chain, exit
.ti -.25i
131 - dump malloc chain, dump core, continue processing
.in -.5i
.P
In addition error messages can be placed into an error file.
.P
\fBmalloc_opt\fP() is used to set the malloc debugging options. The
following options can be set:
.br
.sp
.in +.5i
MALLOC_WARN - set the error handling for warning level errors. \fBval.i\fP is
an integer that can contain any one of the following values:
.sp
.in +.5i
M_HANDLE_IGNORE - ignore error
.br
M_HANDLE_ABORT - drop core and exit
.br
M_HANDLE_EXIT - just exit (no core drop)
.br
M_HANDLE_CORE - drop core, but keep on going
.br
.in -.5i
.sp
In addition, M_HANDLE_DUMP may be or'd in to cause a dump of the current
malloc chain.
.br
.sp
MALLOC_FATAL - set the error handling for fatal level errors. \fBval.i\fP is
equivalent to \fBval.i\fP for MALLOC_WARN.
.br
.sp
MALLOC_ERRFILE - set the destination for malloc error messages. \fBval.str\fP
is a pointer to a character string containing the name of the file to be used
for error messages.
.br
.sp
MALLOC_CKCHAIN - set the malloc chain checking flag. If \fBval.i\fP is
non-zero, chain checking at every call to malloc is turned on.
.br
.sp
For example, to set up the session to generate a core file for
every malloc warning, to drop core and exit on a malloc fatal, and
to log all messages to the file "malloc_log" do the following:
.sp
.nf
.in +.5i
#include <malloc.h>
malloc_opt(MALLOC_WARN,131);
malloc_opt(MALLOC_FATAL,1);
malloc_opt(MALLOC_ERRFILE,"malloc_log");
.in -.5i
.fi
.in -.5i
.sp
\fBmalloc_opt\fP() can be used to set/alter the debugging options at any
time.
.P
\fBmalloc_dump\fP() will dump a table of the malloc arena showing all
allocated/freed segments and the first few bytes of data in each segment.
\fBfd\fP is the file descriptor to write the data to.
.P
\fBmalloc_chain_check\fP() will check the status of the malloc arena.
If \fBflag\fP is non-zero, an error found in the chain will cause a
fatal error. \fBmalloc_chain_check\fP() returns zero when there are no
problems found in the malloc chain, non-zero otherwise.
.SH "ENVIRONMENT VARIABLES"
Environment variables can be used to control error handling, error logging
and malloc chain checking at run time. The following environment variables
are used:
.P
MALLOC_WARN - specifies the error handling for warning errors
.br
MALLOC_FATAL - specifies the error handling for fatal errors
.br
MALLOC_ERRFILE - specifies the error log file for error messages.
.br
MALLOC_CKCHAIN - if 1, turns on malloc chain checking at every call to any
of the malloc functions.
.P
For example, to set up the session to generate a core file for
every malloc warning, to drop core and exit on a malloc fatal, and
to log all messages to the file "malloc_log" do the following:
.sp
.nf
.in +.5i
MALLOC_WARN=131
MALLOC_FATAL=1
MALLOC_ERRFILE=malloc_log
X
export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE
.in -.5i
.fi
.SH WARNINGS
This malloc library and it's associated string and memory functions are
much less efficient than the standard functions due in part to the extra
error checking. You do not want to use this library when generating a
production (i.e. releasable) version of your software. It should only
be used during development and testing.
.SH SEE ALSO
stat(2)
.SH AUTHOR
Conor P. Cahill
Virtual Technologies Incorporated
.sp
uunet!virtech!cpcahil
SHAR_EOF
chmod 0640 dmake/dbug/malloc/malloc.3 ||
echo 'restore of dmake/dbug/malloc/malloc.3 failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/malloc.3'`"
test 6712 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/malloc.3: original size 6712, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/malloc.c ==============
if test -f 'dmake/dbug/malloc/malloc.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/malloc.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/malloc.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
#include "tostring.h"
X
/*
X * Function: malloc()
X *
X * Purpose: memory allocator
X *
X * Arguments: size - size of data area needed
X *
X * Returns: pointer to allocated area, or NULL if unable
X * to allocate addtional data.
X *
X * Narrative:
X *
X */
#ifndef lint
static
char rcs_hdr[] = "$Id: malloc.c,v 1.6 90/05/11 00:13:09 cpcahil Exp $";
#endif
X
extern int malloc_checking;
char * malloc_data_start;
char * malloc_data_end;
struct mlist * malloc_end;
int malloc_errfd = 2;
int malloc_errno;
int malloc_fatal_level = M_HANDLE_CORE;
struct mlist malloc_start;
int malloc_warn_level;
void malloc_memset();
X
char *
malloc(size)
X unsigned int size;
{
X char * func = "malloc";
X char * getenv();
X void malloc_fatal();
X void malloc_init();
X void malloc_split();
X void malloc_warning();
X unsigned int need;
X struct mlist * oldptr;
X struct mlist * ptr;
X char * sbrk();
X
X /*
X * If this is the first call to malloc...
X */
X if( malloc_data_start == (char *) 0 )
X {
X malloc_init();
X }
X
X /*
X * If malloc chain checking is on, go do it.
X */
X if( malloc_checking )
X {
X (void) malloc_chain_check(1);
X }
X
X /*
X * always make sure there is at least on extra byte in the malloc
X * area so that we can verify that the user does not overrun the
X * data area.
X */
X size++;
X
X /*
X * Now look for a free area of memory of size bytes...
X */
X oldptr = NULL;
X for(ptr = &malloc_start; ; ptr = ptr->next)
X {
X /*
X * Since the malloc chain is a forward only chain, any
X * pointer that we get should always be positioned in
X * memory following the previous pointer. If this is not
X * so, we must have a corrupted chain.
X */
X if( ptr )
X {
X if( IsLess(ptr,oldptr) )
X {
X malloc_errno = M_CODE_CHAIN_BROKE;
X malloc_fatal(func);
X return(NULL);
X }
X oldptr = ptr;
X }
X else if( oldptr != malloc_end )
X {
X /*
X * This should never happen. If it does, then
X * we got a real problem.
X */
X malloc_errno = M_CODE_NO_END;
X malloc_fatal(func);
X return(NULL);
X }
X
X
X /*
X * if this element is already in use...
X */
X if( ptr && ((ptr->flag & M_INUSE) != 0) )
X {
X continue;
X }
X
X /*
X * if there isn't room for this block..
X */
X if( ptr && (ptr->s.size < size) )
X {
X continue;
X }
X
X /*
X * If ptr is null, we have run out of memory and must sbrk more
X */
X if( ptr == NULL )
X {
X need = (size + M_SIZE) * (size > 10*1024 ? 1:2);
X if( need < M_BLOCKSIZE )
X {
X need = M_BLOCKSIZE;
X }
X else if( need & (M_BLOCKSIZE-1) )
X {
X need &= ~(M_BLOCKSIZE-1);
X need += M_BLOCKSIZE;
X }
X ptr = (struct mlist *) sbrk((int)need);
X if( ptr == (struct mlist *) -1 )
X {
X malloc_errno = M_CODE_NOMORE_MEM;
X malloc_fatal(func);
X }
X malloc_data_end = sbrk((int)0);
X
X ptr->prev = oldptr;
X ptr->next = (struct mlist *) 0;
X ptr->s.size = need - M_SIZE;
X ptr->flag = M_MAGIC;
X
X oldptr->next = ptr;
X malloc_end = ptr;
X
X
X } /* if( ptr ==... */
X
X /*
X * Now ptr points to a memory location that can store
X * this data, so lets go to work.
X */
X
X ptr->r_size = size; /* save requested size */
X ptr->flag |= M_INUSE;
X
X /*
X * split off unneeded data area in this block, if possible...
X */
X malloc_split(ptr);
X
X /*
X * re-adjust the requested size so that it is what the user
X * actually requested...
X */
X
X ptr->r_size--;
X
X /*
X * just to make sure that noone is misusing malloced
X * memory without initializing it, lets set it to
X * all '\01's. We call local_memset() because memset()
X * may be checking for malloc'd ptrs and this isn't
X * a malloc'd ptr yet.
X */
X malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);
X
X return( ptr->data);
X
X } /* for(... */
X
} /* malloc(... */
X
/*
X * Function: malloc_split()
X *
X * Purpose: to split a malloc segment if there is enough room at the
X * end of the segment that isn't being used
X *
X * Arguments: ptr - pointer to segment to split
X *
X * Returns: nothing of any use.
X *
X * Narrative:
X * get the needed size of the module
X * round the size up to appropriat boundry
X * calculate amount of left over space
X * if there is enough left over space
X * create new malloc block out of remainder
X * if next block is free
X * join the two blocks together
X * fill new empty block with free space filler
X * re-adjust pointers and size of current malloc block
X *
X *
X *
X * Mod History:
X * 90/01/27 cpcahil Initial revision.
X */
void
malloc_split(ptr)
X struct mlist * ptr;
{
X extern struct mlist * malloc_end;
X void malloc_join();
X int rest;
X int size;
X struct mlist * tptr;
X
X size = ptr->r_size;
X
X /*
X * roundup size to the appropriate boundry
X */
X
X M_ROUNDUP(size);
X
X /*
X * figure out how much room is left in the array.
X * if there is enough room, create a new mlist
X * structure there.
X */
X
X if( ptr->s.size > size )
X {
X rest = ptr->s.size - size;
X }
X else
X {
X rest = 0;
X }
X
X if( rest > (M_SIZE+M_RND) )
X {
X tptr = (struct mlist *) (ptr->data+size);
X tptr->prev = ptr;
X tptr->next = ptr->next;
X tptr->flag = M_MAGIC;
X tptr->s.size = rest - M_SIZE;
X
X /*
X * If possible, join this segment with the next one
X */
X
X malloc_join(tptr, tptr->next,0,0);
X
X if( tptr->next )
X {
X tptr->next->prev = tptr;
X }
X
X malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);
X
X ptr->next = tptr;
X ptr->s.size = size;
X
X if( malloc_end == ptr )
X {
X malloc_end = tptr;
X }
X }
X
} /* malloc_split(... */
X
/*
X * Function: malloc_join()
X *
X * Purpose: to join two malloc segments together (if possible)
X *
X * Arguments: ptr - pointer to segment to join to.
X * nextptr - pointer to next segment to join to ptr.
X *
X * Returns: nothing of any values.
X *
X * Narrative:
X *
X * Mod History:
X * 90/01/27 cpcahil Initial revision.
X */
void
malloc_join(ptr,nextptr, inuse_override, fill_flag)
X struct mlist * ptr;
X struct mlist * nextptr;
X int inuse_override;
X int fill_flag;
{
X unsigned int newsize;
X
X if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) &&
X nextptr && ! (nextptr->flag & M_INUSE) &&
X ((ptr->data+ptr->s.size) == (char *) nextptr) )
X {
X if( malloc_end == nextptr )
X {
X malloc_end = ptr;
X }
X ptr->next = nextptr->next;
X newsize = nextptr->s.size + M_SIZE;
X
X /*
X * if we are to fill and this segment is in use,
X * fill in with M_FILL newly added space...
X */
X
X if(fill_flag && (ptr->flag & M_INUSE) )
X {
X malloc_memset(ptr->data+ptr->s.size,
X M_FILL, (int)(nextptr->s.size + M_SIZE));
X }
X
X ptr->s.size += newsize;
X if( ptr->next )
X {
X ptr->next->prev = ptr;
X }
X }
X
} /* malloc_join(... */
X
X
/*
X * The following mess is just to ensure that the versions of these functions in
X * the current library are included (to make sure that we don't accidentaly get
X * the libc versions. (This is the lazy man's -u ld directive)
X */
X
void free();
int strcmp();
int memcmp();
char * realloc();
X
void (*malloc_void_funcs[])() =
{
X free,
};
X
int (*malloc_int_funcs[])() =
{
X strcmp,
X memcmp,
};
X
char * (*malloc_char_star_funcs[])() =
{
X realloc,
};
X
/*
X * This is malloc's own memset which is used without checking the parameters.
X */
X
void
malloc_memset(ptr,byte,len)
X char * ptr;
X char byte;
X int len;
{
X
X while(len-- > 0)
X {
X *ptr++ = byte;
X }
X
} /* malloc_memset(... */
X
/*
X * Function: malloc_fatal()
X *
X * Purpose: to display fatal error message and take approrpriate action
X *
X * Arguments: funcname - name of function calling this routine
X *
X * Returns: nothing of any value
X *
X * Narrative:
X *
X * Notes: This routine does not make use of any libc functions to build
X * and/or disply the error message. This is due to the fact that
X * we are probably at a point where malloc is having a real problem
X * and we don't want to call any function that may use malloc.
X */
void
malloc_fatal(funcname)
X char * funcname;
{
X char errbuf[128];
X void exit();
X void malloc_err_handler();
X extern char * malloc_err_strings[];
X extern int malloc_errno;
X extern int malloc_fatal_level;
X char * s;
X char * t;
X
X s = errbuf;
X t = "Fatal error: ";
X while( *s = *t++)
X {
X s++;
X }
X t = funcname;
X while( *s = *t++)
X {
X s++;
X }
X
X t = "(): ";
X while( *s = *t++)
X {
X s++;
X }
X
X t = malloc_err_strings[malloc_errno];
X while( *s = *t++)
X {
X s++;
X }
X
X *(s++) = '\n';
X
X if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
X {
X (void) write(2,"I/O error to error file\n",(unsigned)24);
X exit(110);
X }
X malloc_err_handler(malloc_fatal_level);
X
} /* malloc_fatal(... */
X
/*
X * Function: malloc_warning()
X *
X * Purpose: to display warning error message and take approrpriate action
X *
X * Arguments: funcname - name of function calling this routine
X *
X * Returns: nothing of any value
X *
X * Narrative:
X *
X * Notes: This routine does not make use of any libc functions to build
X * and/or disply the error message. This is due to the fact that
X * we are probably at a point where malloc is having a real problem
X * and we don't want to call any function that may use malloc.
X */
void
malloc_warning(funcname)
X char * funcname;
{
X char errbuf[128];
X void exit();
X void malloc_err_handler();
X extern char * malloc_err_strings[];
X extern int malloc_errno;
X extern int malloc_warn_level;
X char * s;
X char * t;
X
X s = errbuf;
X t = "Warning: ";
X while( *s = *t++)
X {
X s++;
X }
X t = funcname;
X while( *s = *t++)
X {
X s++;
X }
X
X t = "(): ";
X while( *s = *t++)
X {
X s++;
X }
X
X t = malloc_err_strings[malloc_errno];
X while( *s = *t++)
X {
X s++;
X }
X
X *(s++) = '\n';
X
X if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
X {
X (void) write(2,"I/O error to error file\n",(unsigned)24);
X exit(110);
X }
X
X malloc_err_handler(malloc_warn_level);
X
} /* malloc_warning(... */
X
/*
X * Function: malloc_err_handler()
X *
X * Purpose: to take the appropriate action for warning and/or fatal
X * error conditions.
X *
X * Arguments: level - error handling level
X *
X * Returns: nothing of any value
X *
X * Narrative:
X *
X * Notes: This routine does not make use of any libc functions to build
X * and/or disply the error message. This is due to the fact that
X * we are probably at a point where malloc is having a real problem
X * and we don't want to call any function that may use malloc.
X */
void
malloc_err_handler(level)
{
X void exit();
X void malloc_dump();
X extern int malloc_errfd;
X
X if( level & M_HANDLE_DUMP )
X {
X malloc_dump(malloc_errfd);
X }
X
X switch( level & ~M_HANDLE_DUMP )
X {
X /*
X * If we are to drop a core file and exit
X */
X case M_HANDLE_ABORT:
X (void) abort();
X break;
X
X /*
X * If we are to exit..
X */
X case M_HANDLE_EXIT:
X exit(200);
X break;
X
#ifndef __MSDOS__
X /*
X * If we are to dump a core, but keep going on our merry way
X */
X case M_HANDLE_CORE:
X {
X int pid;
X
X /*
X * fork so child can abort (and dump core)
X */
X if( (pid = fork()) == 0 )
X {
X (void) write(2,"Child dumping core\n",
X (unsigned)9);
X (void) abort();
X }
X
X /*
X * wait for child to finish dumping core
X */
X while( wait((int *)0) != pid)
X {
X }
X
X /*
X * Move core file to core.pid.cnt so
X * multiple cores don't overwrite each
X * other.
X */
X if( access("core",0) == 0 )
X {
X static int corecnt;
X char filenam[32];
X filenam[0] = 'c';
X filenam[1] = 'o';
X filenam[2] = 'r';
X filenam[3] = 'e';
X filenam[4] = '.';
X (void)tostring(filenam+5,getpid(),
X 5, B_DEC, '0');
X filenam[10] = '.';
X (void)tostring(filenam+11,corecnt++,
X 3, B_DEC, '0');
X filenam[14] = '\0';
X (void) unlink(filenam);
X if( link("core",filenam) == 0)
X {
X (void) unlink("core");
X }
X }
X }
#endif
X
X
X /*
X * If we are to just ignore the error and keep on processing
X */
X case M_HANDLE_IGNORE:
X break;
X
X } /* switch(... */
X
} /* malloc_err_handler(... */
X
/*
X * $Log: malloc.c,v $
X * Revision 1.6 90/05/11 00:13:09 cpcahil
X * added copyright statment
X *
X * Revision 1.5 90/02/25 11:01:18 cpcahil
X * added support for malloc chain checking.
X *
X * Revision 1.4 90/02/24 21:50:21 cpcahil
X * lots of lint fixes
X *
X * Revision 1.3 90/02/24 14:51:18 cpcahil
X * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
X * the function name as a parameter.
X * 2. Added several function headers.
X * 3. Changed uses of malloc_fatal/warning to conform to new usage.
X *
X * Revision 1.2 90/02/23 18:05:23 cpcahil
X * fixed open of error log to use append mode.
X *
X * Revision 1.1 90/02/22 23:17:43 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/malloc.c ||
echo 'restore of dmake/dbug/malloc/malloc.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/malloc.c'`"
test 12765 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/malloc.c: original size 12765, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/malloc.h ==============
if test -f 'dmake/dbug/malloc/malloc.h' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/malloc.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/malloc.h' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
/*
X * $Id: malloc.h,v 1.4 90/08/29 22:23:38 cpcahil Exp $
X */
struct mlist
{
X struct mlist * next; /* next entry in chain */
X struct mlist * prev; /* prev entry in chain */
X int flag; /* inuse flag */
X unsigned int r_size; /* requested size */
X union
X {
X unsigned int size; /* actual size */
X double unused_just_for_alignment;
X } s;
X char data[4];
};
X
#define M_SIZE ((int)(char *)((struct mlist *)0)->data)
#define M_RND 0x08
X
#define M_INUSE 0x01
#define M_MAGIC 0x03156100
X
#define M_BLOCKSIZE (1024*8)
X
#define M_FILL '\01'
#define M_FREE_FILL '\02'
X
#define M_ROUNDUP(size) {\
X if( size & (M_RND-1) ) \
X { \
X size &= ~(M_RND-1); \
X size += M_RND; \
X } \
X }
X
/*
X * Malloc warning/fatal error handler defines...
X */
#define M_HANDLE_DUMP 0x80 /* 128 */
#define M_HANDLE_IGNORE 0
#define M_HANDLE_ABORT 1
#define M_HANDLE_EXIT 2
#define M_HANDLE_CORE 3
X
/*
X * Mallopt commands and defaults
X */
X
#define MALLOC_WARN 1 /* set malloc warning handling */
#define MALLOC_FATAL 2 /* set malloc fatal handling */
#define MALLOC_ERRFILE 3 /* specify malloc error file */
#define MALLOC_CKCHAIN 4 /* turn on chain checking */
union malloptarg
{
X int i;
X char * str;
};
X
/*
X * Malloc warning/fatal error codes
X */
X
#define M_CODE_CHAIN_BROKE 1 /* malloc chain is broken */
#define M_CODE_NO_END 2 /* chain end != endptr */
#define M_CODE_BAD_PTR 3 /* pointer not in malloc area */
#define M_CODE_BAD_MAGIC 4 /* bad magic number in header */
#define M_CODE_BAD_CONNECT 5 /* chain poingers corrupt */
#define M_CODE_OVERRUN 6 /* data overrun in malloc seg */
#define M_CODE_REUSE 7 /* reuse of freed area */
#define M_CODE_NOT_INUSE 8 /* pointer is not in use */
#define M_CODE_NOMORE_MEM 9 /* no more memory available */
#define M_CODE_OUTOF_BOUNDS 10 /* gone beyound bounds */
X
void malloc_warning();
void malloc_fatal();
void malloc_check_data();
void malloc_check_str();
void malloc_verify();
X
/*
X * $Log: malloc.h,v $
X * Revision 1.4 90/08/29 22:23:38 cpcahil
X * fixed mallopt to use a union as an argument.
X *
X * Revision 1.3 90/05/11 11:04:10 cpcahil
X * took out some extraneous lines
X *
X * Revision 1.2 90/05/11 00:13:09 cpcahil
X * added copyright statment
X *
X * Revision 1.1 90/02/23 07:09:03 cpcahil
X * Initial revision
X *
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/malloc.h ||
echo 'restore of dmake/dbug/malloc/malloc.h failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/malloc.h'`"
test 2487 -eq "$Wc_c" ||
echo 'dmake/dbug/malloc/malloc.h: original size 2487, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/mallopt.c ==============
if test -f 'dmake/dbug/malloc/mallopt.c' -a X"$1" != X"-c"; then
echo 'x - skipping dmake/dbug/malloc/mallopt.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/mallopt.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
SHAR_EOF
true || echo 'restore of dmake/dbug/malloc/mallopt.c failed'
fi
echo 'End of part 5, continue with part 6'
echo 6 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list