4 * Memory routines with out-of-memory checking.
6 * Copyright 1996-2003 Glyph & Cog, LLC
18 typedef struct _GMemHdr {
21 struct _GMemHdr *next;
24 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
25 #define gMemTrlSize (sizeof(long))
28 #define gMemDeadVal 0xdeadbeefdeadbeefUL
30 #define gMemDeadVal 0xdeadbeefUL
33 /* round data size so trailer will be aligned */
34 #define gMemDataSize(size) \
35 ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
38 #define gMemListShift 4
39 #define gMemListMask (gMemNLists - 1)
40 static GMemHdr *gMemList[gMemNLists] = {
41 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
42 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
43 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
44 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
45 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
48 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
51 static int gMemIndex = 0;
52 static int gMemAlloc = 0;
53 static int gMemInUse = 0;
55 #endif /* DEBUG_MEM */
57 void *gmalloc(int size) {
64 unsigned long *trl, *p;
68 size1 = gMemDataSize(size);
69 if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
70 fprintf(stderr, "Out of memory\n");
74 data = (void *)(mem + gMemHdrSize);
75 trl = (unsigned long *)(mem + gMemHdrSize + size1);
77 hdr->index = gMemIndex++;
78 lst = ((int)hdr >> gMemListShift) & gMemListMask;
79 hdr->next = gMemList[lst];
83 for (p = (unsigned long *)data; p <= trl; ++p)
91 if (!(p = malloc(size))) {
92 fprintf(stderr, "Out of memory\n");
99 void *grealloc(void *p, int size) {
111 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
114 memcpy(q, p, size < oldSize ? size : oldSize);
129 q = realloc(p, size);
133 fprintf(stderr, "Out of memory\n");
140 void *gmallocn(int nObjs, int objSize) {
144 if (objSize == 0 || n / objSize != nObjs) {
145 fprintf(stderr, "Bogus memory allocation size\n");
151 void *greallocn(void *p, int nObjs, int objSize) {
155 if (objSize == 0 || n / objSize != nObjs) {
156 fprintf(stderr, "Bogus memory allocation size\n");
159 return grealloc(p, n);
162 void gfree(void *p) {
166 GMemHdr *prevHdr, *q;
168 unsigned long *trl, *clr;
171 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
172 lst = ((int)hdr >> gMemListShift) & gMemListMask;
173 for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
179 prevHdr->next = hdr->next;
181 gMemList[lst] = hdr->next;
183 gMemInUse -= hdr->size;
184 size = gMemDataSize(hdr->size);
185 trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
186 if (*trl != gMemDeadVal) {
187 fprintf(stderr, "Overwrite past end of block %d at address %p\n",
190 for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
194 fprintf(stderr, "Attempted to free bad address %p\n", p);
204 void gMemReport(FILE *f) {
208 fprintf(f, "%d memory allocations in all\n", gMemIndex);
210 fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
211 fprintf(f, " index size\n");
212 fprintf(f, "-------- --------\n");
213 for (lst = 0; lst < gMemNLists; ++lst) {
214 for (p = gMemList[lst]; p; p = p->next)
215 fprintf(f, "%8d %8d\n", p->index, p->size);
218 fprintf(f, "No memory blocks left allocated\n");
223 char *copyString(char *s) {
226 s1 = (char *)gmalloc(strlen(s) + 1);