1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
/*
------------------------------------------------------------------------------
A license is hereby granted to reproduce this software source code and
to create executable versions from this source code for personal,
non-commercial use. The copyright notice included with the software
must be maintained in all copies produced.
THIS PROGRAM IS PROVIDED "AS IS". THE AUTHOR PROVIDES NO WARRANTIES
WHATSOEVER, EXPRESSED OR IMPLIED, INCLUDING WARRANTIES OF
MERCHANTABILITY, TITLE, OR FITNESS FOR ANY PARTICULAR PURPOSE. THE
AUTHOR DOES NOT WARRANT THAT USE OF THIS PROGRAM DOES NOT INFRINGE THE
INTELLECTUAL PROPERTY RIGHTS OF ANY THIRD PARTY IN ANY COUNTRY.
Copyright (c) 1995, John Conover, All Rights Reserved.
Comments and/or bug reports should be addressed to:
john@johncon.com (John Conover)
------------------------------------------------------------------------------
memalloc.c, memory allocation
void *memalloc (size_t size);
allocate memory area of size, size, and include a reference to the
allocated area in the allocated list
the objective of this allocation routine is to provide a "memory
shutdown" procedure in applications where many allocations are
performed, but there are no deallocations until the program
exits. These are typical requirements of parsing and numerical
method applications. The advantage is that the memory can be
deallocated on command, without maintaining tables of references
to allocated areas. Of particular applicability are client/server
architectures, where memory must be deallocated, without the
program exiting, and memory leaks are to be avoided. The routine
maintains a list, or stack, of elements that reference the
allocated areas-permitting cycling through the list and freeing
all allocated areas.
The algorithm is as follows:
allocate a MEM element
allocate the memory area
push the MEM element on the allocated list
Usage is a call with the desired memory area size, for example:
if ((my_ref = memalloc (size)) == (NULL) 0)
{
allocation_error ();
}
The argument, size, is the size of the area to allocate.
Returns a reference to the allocated area, null if the area could not
be allocated.
$Revision: 1.0 $
$Date: 1995/04/22 05:13:18 $
$Id: memalloc.c,v 1.0 1995/04/22 05:13:18 john Exp $
$Log: memalloc.c,v $
* Revision 1.0 1995/04/22 05:13:18 john
* Initial revision
*
*/
#include "rel.h"
#ifndef LINT /* include rcsid only if not running lint */
static char rcsid[] = "$Id: memalloc.c,v 1.0 1995/04/22 05:13:18 john Exp $"; /* module version */
static char rcsid_h[] = MEMALLOC_H_ID; /* module include version */
#endif
typedef struct mem
{
void *reference; /* reference to allocated area */
struct mem *next; /* reference to next element in the allocated list */
} MEM;
static MEM *mem_stack = (MEM *) 0; /* reference to the allocated list */
#ifdef __STDC__
void *memalloc (size_t size)
#else
void *memalloc (size)
size_t size;
#endif
{
void *retval = (void *) 0; /* return value, assume error */
MEM *ref; /* reference to allocated list element */
if ((ref = (MEM *) malloc (sizeof (MEM))) != (MEM *) 0) /* allocate the allocated list element, fall through if failure */
{
if ((retval = ref->reference = (void *) malloc (size)) != (void *) 0) /* allocate the area */
{
PUSH (mem_stack, ref); /* yes, push the token on the reverse postfix stack */
}
else
{
free ((void *) ref); /* couldn't allocate the area, free the allocated list element */
}
}
return (retval); /* return aq reference to the allocated area */
}
/*
void memdealloc (void);
since memalloc() could be interrupted, a shutdown procedure is
necessary to deallocate memory-this routine should be installed as
part of the interrupt handling process, or prior to the exit of the
program
The algorithm is as follows:
while there are elements on the allocated list
pop the element from the allocated list
free the allocated area referenced by the element
free the element
There are no arguments, and no return value from this function
*/
#ifdef __STDC__
void memdealloc (void)
#else
void memdealloc ()
#endif
{
MEM *ref; /* reference to allocated list element */
while (mem_stack != (MEM *) 0) /* for each element in the allocated list */
{
ref = POP (mem_stack); /* pop the element off the allocated list */
if (ref->reference != 0) /* area allocated? */
{
free ((void *) ref->reference); /* yes, deallocate the area allocated */
}
free ((void *) ref); /* deallocate the list element's memory */
}
}
#ifdef TEST_MEMALLOC
/*
simple exerciser for testing memalloc (); get a string from stdin,
convert it to ascii, and allocate an area of that size; ignore the:
declared global, could be static
memalloc memalloc.c(xxx)
memdealloc memalloc.c(yyy)
from lint
*/
#ifdef __STDC__
int main (void)
#else
int main ()
#endif
{
char buffer[BUFSIZ]; /* buffer to be parsed */
while (gets (buffer) != 0) /* input the size to be allocated */
{
(void) memalloc (atoi (buffer)); /* allocate the area */
}
memdealloc (); /* deallocate memory */
exit (0); /* return any errors */
#ifdef LINT /* include only if running lint */
return (0); /* for LINT formality */
#endif
}
#endif
|