|
|
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) 1986, 1990 by The Trustees of Columbia University in
8: the City of New York. Permission is granted to any individual or
9: institution to use, copy, or redistribute this software so long as it
10: is not sold for profit, provided this copyright notice is retained.
11: */
12: #include <stdio.h>
13: #include "ckcdeb.h"
14: /*
15: memdebug:
16: variable to control memory debugging.
17: if memdebug == 1, then action is always taken.
18: if memdebug == 0, then no action is taken.
19: if memdebug == -1, then the user is asked (works well with gdb).
20: */
21: int memdebug = -1;
22: /*
23: To use this package, compile your program with:
24: -Dmalloc=dmalloc -Dfree=dfree =Dcalloc=dcalloc ... -DMDEBUG
25: and then link it with ckcmdb.c.
26: */
27: #ifdef MDEBUG
28: /* Use the real ones in this module! */
29: #ifdef malloc
30: #undef malloc
31: #endif /* malloc */
32: #ifdef calloc
33: #undef calloc
34: #endif /* calloc */
35: #ifdef realloc
36: #undef realloc
37: #endif /* realloc */
38: #ifdef free
39: #undef free
40: #endif /* free */
41:
42: char *malloc(), *realloc();
43: char *set_range_check(), *check_range();
44:
45: #define min(x,y) ((x) < (y) ? (x) : (y))
46: #define RANGE "ABCDEFGHIJKLMNOP"
47: #define INTSIZE sizeof(int)
48: #define LONGSIZE sizeof(long)
49: #define RSIZE sizeof(RANGE)
50: #define RFRONT min((RSIZE/2),LONGSIZE)
51: #define RBACK min((RSIZE-RFRONT),LONGSIZE)
52:
53: char *
54: dmalloc(size) int size; {
55: char *cp;
56:
57: cp = malloc(size + RSIZE + INTSIZE);
58: if (cp) {
59: cp = set_range_check(cp, size);
60: m_insert(cp);
61: }
62: return(cp);
63: }
64:
65: char *
66: dcalloc(nelem, elsize) int nelem, elsize; {
67: char *cp;
68:
69: cp = dmalloc(nelem * elsize);
70: if (cp)
71: bzero(cp, nelem * elsize);
72: return(cp);
73: }
74:
75: char *
76: drealloc(bp,size) char *bp; int size; {
77: char *cp;
78:
79: if (bp == NULL) {
80: maybe_quit("Freeing NULL pointer");
81: } else {
82: m_delete(bp);
83: cp = check_range(bp);
84: }
85: cp = realloc(cp, size + RSIZE + INTSIZE);
86: if (cp) {
87: cp = set_range_check(cp, size);
88: m_insert(cp);
89: }
90: return(cp);
91: }
92:
93: dfree(cp) char *cp; {
94: if (cp == NULL)
95: maybe_quit("Freeing NULL pointer");
96: else {
97: m_delete(cp);
98: cp = check_range(cp);
99: }
100: return(free(cp));
101: }
102:
103: char *
104: set_range_check(cp,size) char *cp; int size; {
105: register int i;
106: int tmp = size;
107:
108: for(i = 0; i < INTSIZE; i++) { /* set the size in the string */
109: cp[i] = tmp & 0xff;
110: tmp >>= 8;
111: }
112: cp += INTSIZE; /* skip the size */
113:
114: for(i = 0; i < RFRONT; i++) /* set the front of the range check */
115: cp[i] = RANGE[i]; /* string */
116:
117: cp += RFRONT; /* skip the front range check */
118:
119: for(i = 0; i < RBACK; i++) /* set the back odf the range check */
120: cp[i+size] = RANGE[i+RFRONT];
121:
122: return(cp);
123: }
124:
125: /*
126: Put calls to this routine in your code any place where you want to
127: check whether you've copied too many characters into a malloc'd space.
128: */
129: char *
130: check_range(cp) char *cp; {
131: register char *bp = cp - RFRONT - INTSIZE;
132: char *xp = bp;
133: register int i;
134: int size = 0;
135:
136: for(i = 0 ; i < INTSIZE; i++) { /* get the size out of the string */
137: size <<= 8;
138: size |= bp[INTSIZE-i-1] & 0xff;
139: }
140: bp += INTSIZE;
141:
142: for(i = 0; i < RFRONT; i++) /* check front range check */
143: if (bp[i] != RANGE[i]) {
144: maybe_quit("leftside malloc buffer overrun");
145: break;
146: }
147: bp += RFRONT; /* skip front range check */
148:
149: for(i = 0; i < RBACK; i++) /* check back rnage check */
150: if (bp[i+size] != RANGE[i+RFRONT]) {
151: maybe_quit("rightside malloc buffer overrun");
152: break;
153: }
154: return(xp);
155: }
156:
157: #define BUCKETS 10000
158: char *m_used[BUCKETS];
159:
160: VOID
161: m_insert(cp) register char *cp; {
162: register int i;
163:
164: for(i = 0; i < BUCKETS; i++)
165: if (m_used[i] == 0) {
166: m_used[i] = cp;
167: return;
168: }
169: }
170:
171: VOID
172: m_delete(cp) register char *cp; {
173: register int i;
174:
175: for(i = 0; i < BUCKETS; i++)
176: if (m_used[i] == cp) {
177: m_used[i] = 0;
178: return;
179: }
180: maybe_quit("Freeing unmalloc'ed pointer");
181: }
182:
183: VOID
184: m_init() {
185: register int i;
186: for(i = 0; i < BUCKETS; i++)
187: m_used[i] = 0;
188: }
189:
190: VOID
191: m_done() {
192: register int i,j;
193:
194: for(i = 0; i < BUCKETS; i++)
195: if (m_used[i] != 0) {
196: if (memdebug) {
197: if (j == 0)
198: fprintf(stderr,"unfree'ed buffers, indices: ");
199: fprintf(stderr,"%d, ", i);
200: j++;
201: }
202: }
203: if (j)
204: fprintf(stderr,"\n");
205: if (j)
206: maybe_quit("Unfree'ed malloc buffers");
207: }
208:
209: VOID
210: m_checkranges() {
211: int i;
212:
213: for ( i = 0; i < BUCKETS; i++)
214: if (m_used[i])
215: check_range(m_used[i]);
216: }
217:
218: static VOID
219: maybe_quit(str) char *str; {
220: debug(F100,"mdebug maybe_quit","",0);
221: if (memdebug == 0)
222: return;
223: fprintf(stderr,"%s\n",str);
224: if (memdebug == 1)
225: abort();
226: if (memdebug == -1)
227: if (ask("Quit? "))
228: abort();
229: }
230:
231: static int
232: ask(str) char *str; {
233: char buf[100];
234: FILE *in;
235: int fd;
236:
237: fd = dup(fileno(stdin));
238: in = fdopen(fd, "r");
239: while(1) {
240: fprintf(stderr,str);
241: fflush(stderr);
242: if (fgets(buf, 99, in) == NULL) /* EOF? */
243: return(0);
244: if (buf[0] == 'n' || buf[0] == 'N') {
245: fclose(in);
246: return(0);
247: }
248: if (buf[0] == 'y' || buf[0] == 'Y') {
249: fclose(in);
250: return(1);
251: }
252: fprintf(stderr,"please answer y/n.\n");
253: }
254: }
255: #endif /* MDEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.