Back to index

tetex-bin  3.0
gmem.c
Go to the documentation of this file.
00001 /*
00002  * gmem.c
00003  *
00004  * Memory routines with out-of-memory checking.
00005  *
00006  * Copyright 1996-2003 Glyph & Cog, LLC
00007  */
00008 
00009 #include <aconf.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <stddef.h>
00013 #include <string.h>
00014 #include "gmem.h"
00015 
00016 #ifdef DEBUG_MEM
00017 
00018 typedef struct _GMemHdr {
00019   int size;
00020   int index;
00021   struct _GMemHdr *next;
00022 } GMemHdr;
00023 
00024 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
00025 #define gMemTrlSize (sizeof(long))
00026 
00027 #if gmemTrlSize==8
00028 #define gMemDeadVal 0xdeadbeefdeadbeefUL
00029 #else
00030 #define gMemDeadVal 0xdeadbeefUL
00031 #endif
00032 
00033 /* round data size so trailer will be aligned */
00034 #define gMemDataSize(size) \
00035   ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
00036 
00037 #define gMemNLists    64
00038 #define gMemListShift  4
00039 #define gMemListMask  (gMemNLists - 1)
00040 static GMemHdr *gMemList[gMemNLists] = {
00041   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00042   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00043   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00044   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00045   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00046   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00047   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00048   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
00049 };
00050 
00051 static int gMemIndex = 0;
00052 static int gMemAlloc = 0;
00053 
00054 #endif /* DEBUG_MEM */
00055 
00056 void *gmalloc(int size) {
00057 #ifdef DEBUG_MEM
00058   int size1;
00059   char *mem;
00060   GMemHdr *hdr;
00061   void *data;
00062   int lst;
00063   unsigned long *trl, *p;
00064 
00065   if (size == 0)
00066     return NULL;
00067   size1 = gMemDataSize(size);
00068   if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
00069     fprintf(stderr, "Out of memory\n");
00070     exit(1);
00071   }
00072   hdr = (GMemHdr *)mem;
00073   data = (void *)(mem + gMemHdrSize);
00074   trl = (unsigned long *)(mem + gMemHdrSize + size1);
00075   hdr->size = size;
00076   hdr->index = gMemIndex++;
00077   lst = ((int)hdr >> gMemListShift) & gMemListMask;
00078   hdr->next = gMemList[lst];
00079   gMemList[lst] = hdr;
00080   ++gMemAlloc;
00081   for (p = (unsigned long *)data; p <= trl; ++p)
00082     *p = gMemDeadVal;
00083   return data;
00084 #else
00085   void *p;
00086 
00087   if (size == 0)
00088     return NULL;
00089   if (!(p = malloc(size))) {
00090     fprintf(stderr, "Out of memory\n");
00091     exit(1);
00092   }
00093   return p;
00094 #endif
00095 }
00096 
00097 void *grealloc(void *p, int size) {
00098 #ifdef DEBUG_MEM
00099   GMemHdr *hdr;
00100   void *q;
00101   int oldSize;
00102 
00103   if (size == 0) {
00104     if (p)
00105       gfree(p);
00106     return NULL;
00107   }
00108   if (p) {
00109     hdr = (GMemHdr *)((char *)p - gMemHdrSize);
00110     oldSize = hdr->size;
00111     q = gmalloc(size);
00112     memcpy(q, p, size < oldSize ? size : oldSize);
00113     gfree(p);
00114   } else {
00115     q = gmalloc(size);
00116   }
00117   return q;
00118 #else
00119   void *q;
00120 
00121   if (size == 0) {
00122     if (p)
00123       free(p);
00124     return NULL;
00125   }
00126   if (p)
00127     q = realloc(p, size);
00128   else
00129     q = malloc(size);
00130   if (!q) {
00131     fprintf(stderr, "Out of memory\n");
00132     exit(1);
00133   }
00134   return q;
00135 #endif
00136 }
00137 
00138 void gfree(void *p) {
00139 #ifdef DEBUG_MEM
00140   int size;
00141   GMemHdr *hdr;
00142   GMemHdr *prevHdr, *q;
00143   int lst;
00144   unsigned long *trl, *clr;
00145 
00146   if (p) {
00147     hdr = (GMemHdr *)((char *)p - gMemHdrSize);
00148     lst = ((int)hdr >> gMemListShift) & gMemListMask;
00149     for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
00150       if (q == hdr)
00151        break;
00152     }
00153     if (q) {
00154       if (prevHdr)
00155        prevHdr->next = hdr->next;
00156       else
00157        gMemList[lst] = hdr->next;
00158       --gMemAlloc;
00159       size = gMemDataSize(hdr->size);
00160       trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
00161       if (*trl != gMemDeadVal) {
00162        fprintf(stderr, "Overwrite past end of block %d at address %p\n",
00163               hdr->index, p);
00164       }
00165       for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
00166        *clr = gMemDeadVal;
00167       free(hdr);
00168     } else {
00169       fprintf(stderr, "Attempted to free bad address %p\n", p);
00170     }
00171   }
00172 #else
00173   if (p)
00174     free(p);
00175 #endif
00176 }
00177 
00178 #ifdef DEBUG_MEM
00179 void gMemReport(FILE *f) {
00180   GMemHdr *p;
00181   int lst;
00182 
00183   fprintf(f, "%d memory allocations in all\n", gMemIndex);
00184   if (gMemAlloc > 0) {
00185     fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
00186     fprintf(f, " index     size\n");
00187     fprintf(f, "-------- --------\n");
00188     for (lst = 0; lst < gMemNLists; ++lst) {
00189       for (p = gMemList[lst]; p; p = p->next)
00190        fprintf(f, "%8d %8d\n", p->index, p->size);
00191     }
00192   } else {
00193     fprintf(f, "No memory blocks left allocated\n");
00194   }
00195 }
00196 #endif
00197 
00198 char *copyString(char *s) {
00199   char *s1;
00200 
00201   s1 = (char *)gmalloc(strlen(s) + 1);
00202   strcpy(s1, s);
00203   return s1;
00204 }