gmem.c 4.74 KB
Newer Older
Kristian Høgsberg's avatar
Kristian Høgsberg committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * gmem.c
 *
 * Memory routines with out-of-memory checking.
 *
 * Copyright 1996-2003 Glyph & Cog, LLC
 */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
14
#include <limits.h>
Kristian Høgsberg's avatar
Kristian Høgsberg committed
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
#include "gmem.h"

#ifdef DEBUG_MEM

typedef struct _GMemHdr {
  int size;
  int index;
  struct _GMemHdr *next;
} GMemHdr;

#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
#define gMemTrlSize (sizeof(long))

#if gmemTrlSize==8
#define gMemDeadVal 0xdeadbeefdeadbeefUL
#else
#define gMemDeadVal 0xdeadbeefUL
#endif

/* round data size so trailer will be aligned */
#define gMemDataSize(size) \
  ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)

#define gMemNLists    64
#define gMemListShift  4
#define gMemListMask  (gMemNLists - 1)
static GMemHdr *gMemList[gMemNLists] = {
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};

static int gMemIndex = 0;
static int gMemAlloc = 0;
54
static int gMemInUse = 0;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
55 56 57

#endif /* DEBUG_MEM */

58
void *gmalloc(size_t size) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
59
#ifdef DEBUG_MEM
60
  size_t size1;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
61 62 63 64 65 66
  char *mem;
  GMemHdr *hdr;
  void *data;
  int lst;
  unsigned long *trl, *p;

67
  if (size <= 0)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    return NULL;
  size1 = gMemDataSize(size);
  if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
    fprintf(stderr, "Out of memory\n");
    exit(1);
  }
  hdr = (GMemHdr *)mem;
  data = (void *)(mem + gMemHdrSize);
  trl = (unsigned long *)(mem + gMemHdrSize + size1);
  hdr->size = size;
  hdr->index = gMemIndex++;
  lst = ((int)hdr >> gMemListShift) & gMemListMask;
  hdr->next = gMemList[lst];
  gMemList[lst] = hdr;
  ++gMemAlloc;
83
  gMemInUse += size;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
84 85 86 87 88 89
  for (p = (unsigned long *)data; p <= trl; ++p)
    *p = gMemDeadVal;
  return data;
#else
  void *p;

90
  if (size <= 0)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
91 92 93 94 95 96 97 98 99
    return NULL;
  if (!(p = malloc(size))) {
    fprintf(stderr, "Out of memory\n");
    exit(1);
  }
  return p;
#endif
}

100
void *grealloc(void *p, size_t size) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
101 102 103
#ifdef DEBUG_MEM
  GMemHdr *hdr;
  void *q;
104
  size_t oldSize;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
105

106
  if (size <= 0) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    if (p)
      gfree(p);
    return NULL;
  }
  if (p) {
    hdr = (GMemHdr *)((char *)p - gMemHdrSize);
    oldSize = hdr->size;
    q = gmalloc(size);
    memcpy(q, p, size < oldSize ? size : oldSize);
    gfree(p);
  } else {
    q = gmalloc(size);
  }
  return q;
#else
  void *q;

124
  if (size <= 0) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    if (p)
      free(p);
    return NULL;
  }
  if (p)
    q = realloc(p, size);
  else
    q = malloc(size);
  if (!q) {
    fprintf(stderr, "Out of memory\n");
    exit(1);
  }
  return q;
#endif
}

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
void *gmallocn(int nObjs, int objSize) {
  int n;

  n = nObjs * objSize;
  if (objSize == 0 || n / objSize != nObjs) {
    fprintf(stderr, "Bogus memory allocation size\n");
    exit(1);
  }
  return gmalloc(n);
}

void *greallocn(void *p, int nObjs, int objSize) {
  int n;

  n = nObjs * objSize;
  if (objSize == 0 || n / objSize != nObjs) {
    fprintf(stderr, "Bogus memory allocation size\n");
    exit(1);
  }
  return grealloc(p, n);
}

Kristian Høgsberg's avatar
Kristian Høgsberg committed
163 164
void gfree(void *p) {
#ifdef DEBUG_MEM
165
  size_t size;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  GMemHdr *hdr;
  GMemHdr *prevHdr, *q;
  int lst;
  unsigned long *trl, *clr;

  if (p) {
    hdr = (GMemHdr *)((char *)p - gMemHdrSize);
    lst = ((int)hdr >> gMemListShift) & gMemListMask;
    for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
      if (q == hdr)
	break;
    }
    if (q) {
      if (prevHdr)
	prevHdr->next = hdr->next;
      else
	gMemList[lst] = hdr->next;
      --gMemAlloc;
184
      gMemInUse -= hdr->size;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198
      size = gMemDataSize(hdr->size);
      trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
      if (*trl != gMemDeadVal) {
	fprintf(stderr, "Overwrite past end of block %d at address %p\n",
		hdr->index, p);
      }
      for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
	*clr = gMemDeadVal;
      free(hdr);
    } else {
      fprintf(stderr, "Attempted to free bad address %p\n", p);
    }
  }
#else
Albert Astals Cid's avatar
Albert Astals Cid committed
199
  free(p);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
#endif
}

#ifdef DEBUG_MEM
void gMemReport(FILE *f) {
  GMemHdr *p;
  int lst;

  fprintf(f, "%d memory allocations in all\n", gMemIndex);
  if (gMemAlloc > 0) {
    fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
    fprintf(f, " index     size\n");
    fprintf(f, "-------- --------\n");
    for (lst = 0; lst < gMemNLists; ++lst) {
      for (p = gMemList[lst]; p; p = p->next)
	fprintf(f, "%8d %8d\n", p->index, p->size);
    }
  } else {
    fprintf(f, "No memory blocks left allocated\n");
  }
}
#endif

char *copyString(char *s) {
  char *s1;

  s1 = (char *)gmalloc(strlen(s) + 1);
  strcpy(s1, s);
  return s1;
}