Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
safemem.c
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file safemem.c
5 
6  \version V1.3
7  \date 07.07.14
8  \brief Safe malloc()/free() routines which check for array
9  overflow on free.
10 
11  \copyright (c) UCL / Dr. Andrew C. R. Martin 1995-2014
12  \author Dr. Andrew C. R. Martin
13  \par
14  Institute of Structural & Molecular Biology,
15  University College London,
16  Gower Street,
17  London.
18  WC1E 6BT.
19  \par
20  andrew@bioinf.org.uk
21  andrew.martin@ucl.ac.uk
22 
23 **************************************************************************
24 
25  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
26  according to the conditions laid out in the accompanying file
27  COPYING.DOC.
28 
29  The code may be modified as required, but any modifications must be
30  documented so that the person responsible can be identified.
31 
32  The code may not be sold commercially or included as part of a
33  commercial product except as described in the file COPYING.DOC.
34 
35 **************************************************************************
36 
37  Description:
38  ============
39 
40  blSafemalloc() and blSafefree() are provided as temporary debugging
41  replacements for malloc() and free(). They maintain their own
42  linked list of malloc()'d memory and allocate a `protection buffer'
43  each side of the requested amount of memory. This is filled with a
44  given pattern and, when safefree() is called, this buffer is
45  checked to ensure the pattern is still present.
46 
47  Unlike free(), blSafefree() is of type BOOL, returning TRUE if
48  an error occured.
49 
50 \par SM_SIZE Environment Variable
51 
52  The size of the buffer (default 256bytes each side) may be
53  controlled by the environment variable SM_SIZE. If code continues
54  to core dump, try increasing the value of SM_SIZE.
55 
56 \par SM_FILL Environment Variable
57 
58  The byte used for filling the protection buffers (default 255) is
59  defined by the environment variable SM_FILL. If code which core
60  dumps with normal malloc()/free(), but not with blSafemalloc() /
61  blSafefree(), yet no error message is generated, the character which
62  is corrupting memory is probably the same as the fill character.
63  Try modifying SM_FILL.
64 
65 **************************************************************************
66 
67  Usage:
68  ======
69  NOTE: safemem.h must be included *after* macros.h
70 
71 **************************************************************************
72 
73  Revision History:
74  =================
75 - V1.0 23.06.95 Original
76 - V1.1 27.02.98 Added cast to ptr
77 - V1.2 03.07.06 Added 'ok' to the MEMLIST and added safeleaks()
78 - V1.3 07.07.14 Use bl prefix for functions By: CTP
79 
80 *************************************************************************/
81 /* Doxygen
82  -------
83  #GROUP General Programming
84  #SUBGROUP Memory management
85  #FUNCTION blSafemalloc()
86  Debugging version of malloc() which creates protection buffers each
87  side of the requested memory block.
88 
89  #FUNCTION blSafefree()
90  Debugging version of free() which checks protection buffers each
91  side of the requested memory block.
92 
93  #FUNCTION blSafeleaks()
94  Prints a list of any safemalloc()'d memory which was not freed
95 */
96 /************************************************************************/
97 /* Includes - Note we must *not* include safemem.h since we require the
98  standard versions of INITPREV, ALLOCNEXTPREV, etc.
99 */
100 #include <stdio.h>
101 #include <stdlib.h>
102 #include "macros.h"
103 #include "SysDefs.h"
104 
105 /************************************************************************/
106 /* Defines and macros
107 */
108 #define CHECKSIZE 256 /* Default protection buffer size */
109 #define BLANK (char)(0xFF) /* Default blanking character */
110 #define MAXBYTE 8 /* Max bytes occupied by an address */
111 
112 typedef struct _memlist
113 {
114  char *start;
115  struct _memlist *next,
116  *prev;
117  int length;
119 } MEMLIST;
120 
121 /************************************************************************/
122 /* Globals
123 */
124 static MEMLIST *sSafeMemList = NULL;
125 static int sCheckSize = CHECKSIZE;
126 static char sBlank = BLANK;
127 
128 /************************************************************************/
129 /* Prototypes
130 */
131 
132 /************************************************************************/
133 /*>void *blSafemalloc(int nbytes)
134  ------------------------------
135 *//**
136  \param[in] nbytes Number of bytes to allocate
137  \return Pointer to block of memory
138 
139  Debugging version of malloc() which creates protection buffers each
140  side of the requested memory block.
141 
142 - 23.06.95 Original By: ACRM
143 - 07.07.14 Use bl prefix for functions By: CTP
144 */
145 void *blSafemalloc(int nbytes)
146 {
147  MEMLIST *p;
148  static BOOL FirstCall = TRUE;
149  MEMLIST *q;
150  char *start;
151  int i;
152 
153  /* On first call, check for environment variables */
154  if(FirstCall)
155  {
156  char *envvar;
157  int PadValue;
158 
159  /* Get the protection buffer size (bytes each side of the requested
160  chunk of memory
161  */
162  if((envvar = getenv("SM_SIZE"))!=NULL)
163  {
164  if(sscanf(envvar,"%d",&sCheckSize))
165  {
166  /* Ensure sCheckSize is a multiple of MAXBYTE */
167  if(sCheckSize%MAXBYTE)
168  sCheckSize = (1 + (int)(sCheckSize/MAXBYTE)) * MAXBYTE;
169  }
170  else
171  {
172  fprintf(stderr,"Env. variable, SM_SIZE, is invalid.\n");
173  }
174  }
175 
176  /* Get the padding character to use */
177  if((envvar = getenv("SM_FILL"))!=NULL)
178  {
179  if(sscanf(envvar,"%d",&PadValue))
180  {
181  if(PadValue > 255)
182  fprintf(stderr,"Env. variable, SM_FILL, has been \
183 shortened to the LSB.\n");
184  sBlank = PadValue%256;
185  }
186  else
187  {
188  fprintf(stderr,"Env. variable, SM_FILL, is invalid.\n");
189  }
190  }
191 
192  FirstCall = FALSE;
193  }
194 
195  /* Allocate space in our linked list */
196  if(sSafeMemList==NULL)
197  {
198  INITPREV(sSafeMemList, MEMLIST);
199  p=sSafeMemList;
200  }
201  else
202  {
203  p=sSafeMemList;
204  LAST(p);
206  }
207  if(p==NULL)
208  return(NULL);
209 
210  /* Allocate the requested memory plus the protection space */
211  if((start=(char *)malloc(nbytes+(2*sCheckSize)))==NULL)
212  {
213  /* Remove position from our linked list if allocation failed */
214  q = p->prev;
215  p->prev->next = NULL;
216  free(p);
217  p = q;
218  return(NULL);
219  }
220  p->start = start+sCheckSize;
221  p->length = nbytes;
222  p->ok = TRUE;
223 
224  /* Blank the protection buffer space */
225  for(i=0; i<sCheckSize; i++)
226  {
227  start[i] = sBlank;
228  start[i+nbytes+sCheckSize]=sBlank;
229  }
230 
231  return((void *)(p->start));
232 }
233 
234 /************************************************************************/
235 /*>void blSafefree(void *ptr)
236  --------------------------
237 *//**
238 
239  Debugging version of free() which checks protection buffers each
240  side of the requested memory block.
241 
242 - 23.06.95 Original By: ACRM
243 - 27.02.98 Added cast to ptr
244 - 07.07.14 Use bl prefix for functions By: CTP
245 */
246 BOOL blSafefree(void *ptr)
247 {
248  MEMLIST *p;
249  int i,
250  count=0;
251 
252  /* Search our linked list for this address */
253  for(p=sSafeMemList; p!=NULL; NEXT(p))
254  {
255  count++;
256 
257  if(p->start==(char *)ptr) /* Found it... */
258  {
259  /* Check for array underflow */
260  for(i=sCheckSize; i>0; i--)
261  {
262  if((*(p->start-i) != sBlank))
263  {
264  fprintf(stderr,"safefree(): Array underflow at \
265 %lu by %d bytes\n", (ULONG)ptr,i);
266  p->ok = FALSE;
267  return(TRUE);
268  }
269  }
270  /* Check for array overflow */
271  for(i=sCheckSize-1; i>=0; i--)
272  {
273  if(*(p->start+p->length+i) != sBlank)
274  {
275  fprintf(stderr,"safefree(): Array overflow at \
276 %lu by %d bytes\n", (ULONG)ptr,i+1);
277  p->ok = FALSE;
278  return(TRUE);
279  }
280  }
281 
282  /* No under/over-flow, free the memory and unlink from list */
283  free(p->start-sCheckSize);
284 
285  /* Unlink this item from the memory list */
286  if(p == sSafeMemList)
287  {
288  NEXT(sSafeMemList);
289  if(sSafeMemList)
290  sSafeMemList->prev = NULL;
291  }
292  else
293  {
294  if(p->prev)
295  p->prev->next=p->next;
296  if(p->next)
297  p->next->prev=p->prev;
298  }
299  free(p);
300  return(FALSE);
301  }
302  }
303 
304  /* Specified address not found in our linked list */
305  fprintf(stderr,"safefree(): Bad address passed to free: %lu\n",
306  (ULONG)ptr);
307  fprintf(stderr," %d items in memory list\n",count);
308 
309  return(TRUE);
310 }
311 
312 /************************************************************************/
313 /*>void blSafeleaks(void)
314  ----------------------
315 *//**
316 
317  Prints a list of any safemalloc()'d memory which was not freed
318 
319 - 03.07.06 Original By: ACRM
320 - 07.07.14 Use bl prefix for functions By: CTP
321 */
322 void blSafeleaks(void)
323 {
324  MEMLIST *p;
325  for(p=sSafeMemList; p!=NULL; NEXT(p))
326  {
327  if(p->ok)
328  {
329  fprintf(stderr,"safeleaks(): Leaked memory at: %lu of size: \
330 %lu\n",
331  (long unsigned)p->start, (long unsigned)p->length);
332  }
333  }
334 }
struct _memlist * next
Definition: safemem.c:115
#define ALLOCNEXTPREV(x, y)
Definition: macros.h:254
short BOOL
Definition: SysDefs.h:64
#define LAST(x)
Definition: macros.h:259
#define NULL
Definition: array2.c:99
#define MAXBYTE
Definition: safemem.c:110
int length
Definition: safemem.c:117
struct _memlist * prev
Definition: safemem.c:115
#define FALSE
Definition: macros.h:223
#define NEXT(x)
Definition: macros.h:249
Useful macros.
char * start
Definition: safemem.c:114
void * blSafemalloc(int nbytes)
Definition: safemem.c:145
#define CHECKSIZE
Definition: safemem.c:108
unsigned long ULONG
Definition: SysDefs.h:66
BOOL ok
Definition: safemem.c:118
#define TRUE
Definition: macros.h:219
#define BLANK
Definition: safemem.c:109
struct _memlist MEMLIST
System-type variable type definitions.
void blSafeleaks(void)
Definition: safemem.c:322
BOOL blSafefree(void *ptr)
Definition: safemem.c:246
#define INITPREV(x, y)
Definition: macros.h:246