|
|
1.1 root 1: /*
2: C K C M D B . C -- malloc debugger.
3: */
4:
5: /*
6: Author: Howie Kaye, Columbia University Center for Computing Activities.
7: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
8: York. Permission is granted to any individual or institution to use this
9: software as long as it is not sold for profit. This copyright notice must be
10: retained. This software may not be included in commercial products without
11: written permission of Columbia University.
12: */
13: #include <stdio.h>
14: #include "ckcdeb.h"
15: /*
16: memdebug:
17: variable to control memory debugging.
18: if memdebug == 1, then action is always taken.
19: if memdebug == 0, then no action is taken.
20: if memdebug == -1, then the user is asked (works well with gdb).
21: */
22: int memdebug = -1;
23: int disabled = 0;
24: int inited = 0;
25: /*
26: To use this package, compile your program with:
27: -Dmalloc=dmalloc -Dfree=dfree =Dcalloc=dcalloc ... -DMDEBUG
28: and then link it with ckcmdb.c.
29: */
30: #ifdef MDEBUG
31: /* Use the real ones in this module! */
32: #ifdef malloc
33: #undef malloc
34: #endif /* malloc */
35: #ifdef calloc
36: #undef calloc
37: #endif /* calloc */
38: #ifdef realloc
39: #undef realloc
40: #endif /* realloc */
41: #ifdef free
42: #undef free
43: #endif /* free */
44:
45: char *malloc(), *realloc();
46: char *set_range_check();
47: char *check_range();
48: char *maybe_check_range();
49:
50: #define min(x,y) ((x) < (y) ? (x) : (y))
51: #define RANGE "ABCDEFGHIJKLMNOP"
52: #define INTSIZE sizeof(int)
53: #define LONGSIZE sizeof(long)
54: #define RSIZE sizeof(RANGE)
55: #define RFRONT min((RSIZE/2),LONGSIZE)
56: #define RBACK min((RSIZE-RFRONT),LONGSIZE)
57:
58: char *
59: dmalloc(size) int size; {
60: char *cp;
61:
62: cp = malloc(size + RSIZE + INTSIZE);
63: if (cp) {
64: cp = set_range_check(cp, size);
65: m_insert(cp);
66: }
67: return(cp);
68: }
69:
70: char *
71: dcalloc(nelem, elsize) int nelem, elsize; {
72: char *cp;
73:
74: cp = dmalloc(nelem * elsize);
75: if (cp)
76: bzero(cp, nelem * elsize);
77: return(cp);
78: }
79:
80: char *
81: drealloc(bp,size) char *bp; int size; {
82: char *cp;
83:
84: if (bp == NULL) {
85: maybe_quit("Freeing NULL pointer");
86: } else {
87: m_delete(bp);
88: cp = check_range(bp);
89: }
90: cp = realloc(cp, size + RSIZE + INTSIZE);
91: if (cp) {
92: cp = set_range_check(cp, size);
93: m_insert(cp);
94: }
95: return(cp);
96: }
97:
98: dfree(cp) char *cp; {
99: if (cp == NULL)
100: maybe_quit("Freeing NULL pointer");
101: else {
102: switch(m_delete(cp)) {
103: case 0:
104: cp = maybe_check_range(cp);
105: break;
106: case 1:
107: cp = check_range(cp);
108: break;
109: case 2:
110: break;
111: }
112: }
113: return(free(cp));
114: }
115:
116: char *
117: set_range_check(cp,size) char *cp; int size; {
118: register int i;
119: int tmp = size;
120:
121: for(i = 0; i < INTSIZE; i++) { /* set the size in the string */
122: cp[i] = tmp & 0xff;
123: tmp >>= 8;
124: }
125: cp += INTSIZE; /* skip the size */
126:
127: for(i = 0; i < RFRONT; i++) /* set the front of the range check */
128: cp[i] = RANGE[i]; /* string */
129:
130: cp += RFRONT; /* skip the front range check */
131:
132: for(i = 0; i < RBACK; i++) /* set the back odf the range check */
133: cp[i+size] = RANGE[i+RFRONT];
134:
135: return(cp);
136: }
137:
138: /*
139: Put calls to this routine in your code any place where you want to
140: check whether you've copied too many characters into a malloc'd space.
141: */
142: char *
143: check_range(cp) char *cp; {
144: register char *bp = cp - RFRONT - INTSIZE;
145: char *xp = bp;
146: register int i;
147: int size = 0;
148:
149: for(i = 0 ; i < INTSIZE; i++) { /* get the size out of the string */
150: size <<= 8;
151: size |= bp[INTSIZE-i-1] & 0xff;
152: }
153: bp += INTSIZE;
154:
155: for(i = 0; i < RFRONT; i++) /* check front range check */
156: if (bp[i] != RANGE[i]) {
157: maybe_quit("leftside malloc buffer overrun");
158: break;
159: }
160: bp += RFRONT; /* skip front range check */
161:
162: for(i = 0; i < RBACK; i++) /* check back range check */
163: if (bp[i+size] != RANGE[i+RFRONT]) {
164: maybe_quit("rightside malloc buffer overrun");
165: break;
166: }
167: return(xp);
168: }
169:
170: static char *
171: maybe_check_range(cp) char *cp; {
172: register char *bp = cp - RFRONT - INTSIZE;
173: char *xp = bp;
174: register int i;
175: int size = 0;
176:
177: for(i = 0 ; i < INTSIZE; i++) { /* get the size out of the string */
178: size <<= 8;
179: size |= bp[INTSIZE-i-1] & 0xff;
180: }
181: bp += INTSIZE;
182:
183: for(i = 0; i < RFRONT; i++) /* check front range check */
184: if (bp[i] != RANGE[i]) {
185: return(cp);
186: }
187: bp += RFRONT; /* skip front range check */
188:
189: for(i = 0; i < RBACK; i++) /* check back range check */
190: if (bp[i+size] != RANGE[i+RFRONT]) {
191: fprintf(stderr,"rightside malloc buffer overrun\n");
192: abort();
193: break;
194: }
195: return(xp);
196: }
197:
198: #define BUCKETS 10000
199: char *m_used[BUCKETS];
200: char *m_used2[BUCKETS];
201:
202: VOID
203: m_insert(cp) register char *cp; {
204: register int i;
205:
206: if (disabled)
207: return;
208:
209: for(i = 0; i < BUCKETS; i++)
210: if (m_used[i] == 0) {
211: m_used[i] = cp;
212: return;
213: }
214: disabled ++;
215: }
216:
217: static
218: m_insert2(cp) register char *cp; {
219: register int i;
220:
221: if (disabled)
222: return;
223: for(i = 0; i < BUCKETS; i++)
224: if (m_used2[i] == 0) {
225: m_used2[i] = cp;
226: return;
227: }
228: disabled ++;
229: }
230:
231: VOID
232: m_delete(cp) register char *cp; {
233: register int i;
234:
235: for(i = 0; i < BUCKETS; i++)
236: if (m_used[i] == cp) {
237: m_used[i] = 0;
238: return(1);
239: }
240: for(i = 0; i < BUCKETS; i++)
241: if (m_used2[i] == cp) {
242: m_used2[i] = 0;
243: return(2);
244: }
245: if (disabled)
246: return(0);
247:
248: maybe_quit("Freeing unmalloc'ed pointer");
249: return(0);
250: }
251:
252: VOID
253: m_init() {
254: register int i;
255:
256: inited = 1;
257: disabled = 0;
258: for(i = 0; i < BUCKETS; i++)
259: m_used[i] = 0;
260: }
261:
262: VOID
263: m_done() {
264: register int i,j=0;
265:
266: if (disabled)
267: return;
268: for(i = 0; i < BUCKETS; i++)
269: if (m_used[i] != 0) {
270: if (memdebug) {
271: if (j == 0)
272: fprintf(stderr,"unfree'ed buffers, indices: ");
273: fprintf(stderr,"%d, ", i);
274: j++;
275: }
276: }
277: if (j)
278: fprintf(stderr,"\n");
279: for(i = 0; i < BUCKETS; i++)
280: if (m_used2[i] != 0) {
281: if (memdebug) {
282: if (j == 0)
283: fprintf(stderr,"unfree'ed registered buffers, indices: ");
284: fprintf(stderr,"%d, ", i);
285: j++;
286: }
287: }
288: if (j)
289: fprintf(stderr,"\n");
290: if (j)
291: maybe_quit("Unfree'ed malloc buffers");
292: }
293:
294: VOID
295: m_checkranges() {
296: int i;
297:
298: for ( i = 0; i < BUCKETS; i++)
299: if (m_used[i])
300: check_range(m_used[i]);
301: }
302:
303: static VOID
304: maybe_quit(str) char *str; {
305: debug(F100,"mdebug maybe_quit","",0);
306: if (memdebug == 0)
307: return;
308: fprintf(stderr,"%s\n",str);
309: if (memdebug == 1)
310: abort();
311: if (memdebug == -1)
312: if (ask("Quit? "))
313: abort();
314: }
315:
316: static int
317: ask(str) char *str; {
318: char buf[100];
319: FILE *in;
320: int fd;
321:
322: fd = dup(fileno(stdin));
323: in = fdopen(fd, "r");
324: while(1) {
325: fprintf(stderr,str);
326: fflush(stderr);
327: if (fgets(buf, 99, in) == NULL) /* EOF? */
328: return(0);
329: if (buf[0] == 'n' || buf[0] == 'N') {
330: fclose(in);
331: return(0);
332: }
333: if (buf[0] == 'y' || buf[0] == 'Y') {
334: fclose(in);
335: return(1);
336: }
337: fprintf(stderr,"please answer y/n.\n");
338: }
339: }
340: #endif /* MDEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.