source: trunk/third/kermit/ckcmdb.c @ 20081

Revision 20081, 8.5 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20080, which included commits to RCS files with non-trunk default branches.
Line 
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
8  Copyright (C) 1985, 1999,
9    Trustees of Columbia University in the City of New York.
10    All rights reserved.  See the C-Kermit COPYING.TXT file or the
11    copyright text in the ckcmai.c module for disclaimer and permissions.
12*/
13/* Use the real ones in this module! */
14#ifdef malloc
15#undef malloc
16#endif /* malloc */
17#ifdef calloc
18#undef calloc
19#endif /* calloc */
20#ifdef realloc
21#undef realloc
22#endif /* realloc */
23#ifdef free
24#undef free
25#endif /* free */
26
27#include "ckcsym.h"
28#include <stdio.h>
29#include "ckcdeb.h"
30
31#ifdef COHERENT
32_PROTOTYP ( FILE * fdopen, (int, char *) );
33#endif /* COHERENT */
34
35/*
36  memdebug:
37  variable to control memory debugging.
38  if memdebug ==  1, then action is always taken.
39  if memdebug ==  0, then no action is taken.
40  if memdebug == -1, then the user is asked (works well with gdb).
41*/
42int memdebug = -1;
43int disabled = 0;
44int inited = 0;
45/*
46  To use this package, compile your program with:
47  -Dmalloc=dmalloc -Dfree=dfree =Dcalloc=dcalloc ... -DMDEBUG
48  and then link it with ckcmdb.c.
49*/
50#ifdef MDEBUG
51
52#ifndef M_SIZE_T
53#ifdef NEXT
54#define M_SIZE_T size_t
55#else
56#ifdef SUNOS41
57#define M_SIZE_T unsigned
58#else
59#define M_SIZE_T int
60#endif /* SUNOS41 */
61#endif /* NEXT */
62#endif /* M_SIZE_T */
63
64#ifdef CK_ANSIC
65_PROTOTYP( void free, (void *) );
66_PROTOTYP( void * malloc, (size_t) );
67_PROTOTYP( void * realloc, (void *, size_t) );
68#else
69_PROTOTYP( VOID free, (char *) );
70_PROTOTYP( char * malloc, (M_SIZE_T) );
71_PROTOTYP( char * realloc, (char *, M_SIZE_T) );
72#endif /* NEXT */
73
74_PROTOTYP( VOID m_insert, (char *) );
75_PROTOTYP( int m_delete, (char *) );
76
77_PROTOTYP( char * dmalloc, (int) );
78_PROTOTYP( char * dcalloc, (int, int) );
79_PROTOTYP( char * drealloc, (char *, int) );
80
81_PROTOTYP( char *set_range_check, (char *, int) );
82_PROTOTYP( char *check_range, (char *) );
83_PROTOTYP( static char *maybe_check_range, (char *) );
84
85_PROTOTYP( static VOID maybe_quit, (char *) );
86_PROTOTYP( static int ask, (char *) );
87
88#ifndef min
89#define min(x,y) ((x) < (y) ? (x) : (y))
90#endif /* min */
91#define RANGE "ABCDEFGHIJKLMNOP"
92#define INTSIZE  sizeof(int)
93#define LONGSIZE sizeof(long)
94#define RSIZE    sizeof(RANGE)
95#define RFRONT   min((RSIZE/2),LONGSIZE)
96#define RBACK    min((RSIZE-RFRONT),LONGSIZE)
97
98char *
99dmalloc(size) int size; {
100    char *cp;
101
102    cp = malloc(size + RSIZE + INTSIZE);
103    if (cp) {
104        cp = set_range_check(cp, size);
105        m_insert(cp);
106    }
107    return(cp);
108}
109
110char *
111dcalloc(nelem, elsize) int nelem, elsize; {
112    char *cp;
113
114    cp = dmalloc(nelem * elsize);
115    if (cp)
116        memset(cp, 0, nelem * elsize);
117    return(cp);
118}
119
120char *
121drealloc(bp,size) char *bp; int size; {
122    char *cp;
123
124    if (bp == NULL) {
125        maybe_quit("Freeing NULL pointer");
126    } else {
127        m_delete(bp);
128        cp = check_range(bp);
129    }
130    cp = realloc(cp, size + RSIZE + INTSIZE);
131    if (cp) {
132        cp = set_range_check(cp, size);
133        m_insert(cp);
134    }
135    return(cp);
136}
137
138VOID
139dfree(cp) char *cp; {
140    if (cp == NULL)
141        maybe_quit("Freeing NULL pointer");
142    else {
143        switch(m_delete(cp)) {
144        case 0:
145            cp = maybe_check_range(cp);
146            break;
147        case 1:
148            cp = check_range(cp);
149            break;
150        case 2:
151            break;
152        }
153    }
154#ifndef CK_ANSIC
155    return(free(cp));
156#endif /* CK_ANSIC */
157}
158
159char *
160set_range_check(cp,size) char *cp; int size; {
161    register int i;
162    int tmp = size;
163
164    for(i = 0; i < INTSIZE; i++) {      /* set the size in the string */
165        cp[i] = tmp & 0xff;
166        tmp >>= 8;
167    }
168    cp += INTSIZE;                      /* skip the size */
169
170    for(i = 0; i < RFRONT; i++)         /* set the front of the range check */
171        cp[i] = RANGE[i];               /* string */
172
173    cp += RFRONT;                       /* skip the front range check */
174
175    for(i = 0; i < RBACK; i++)          /* set the back odf the range check */
176        cp[i+size] = RANGE[i+RFRONT];
177
178    return(cp);
179}
180
181/*
182  Put calls to this routine in your code any place where you want to
183  check whether you've copied too many characters into a malloc'd space.
184*/
185char *
186check_range(cp) char *cp; {
187    register char *bp = cp - RFRONT - INTSIZE;
188    char *xp = bp;
189    register int i;
190    int size = 0;
191
192    for(i = 0 ; i < INTSIZE; i++) {     /* get the size out of the string */
193        size <<= 8;
194        size |= bp[INTSIZE-i-1] & 0xff;
195    }
196    bp += INTSIZE;
197
198    for(i = 0; i < RFRONT; i++)         /* check front range check */
199        if (bp[i] != RANGE[i]) {
200            maybe_quit("leftside malloc buffer overrun");
201            break;
202        }
203    bp += RFRONT;                       /* skip front range check */
204
205    for(i = 0; i < RBACK; i++)          /* check back range check */
206        if (bp[i+size] != RANGE[i+RFRONT]) {
207            maybe_quit("rightside malloc buffer overrun");
208            break;
209        }
210    return(xp);
211}
212
213static char *
214maybe_check_range(cp) char *cp; {
215    register char *bp = cp - RFRONT - INTSIZE;
216    char *xp = bp;
217    register int i;
218    int size = 0;
219
220    for(i = 0 ; i < INTSIZE; i++) {     /* get the size out of the string */
221        size <<= 8;
222        size |= bp[INTSIZE-i-1] & 0xff;
223    }
224    bp += INTSIZE;
225
226    for(i = 0; i < RFRONT; i++)         /* check front range check */
227        if (bp[i] != RANGE[i]) {
228            return(cp);
229        }
230    bp += RFRONT;                       /* skip front range check */
231
232    for(i = 0; i < RBACK; i++)          /* check back range check */
233        if (bp[i+size] != RANGE[i+RFRONT]) {
234            fprintf(stderr,"rightside malloc buffer overrun\n");
235            abort();
236            break;
237        }
238    return(xp);
239}
240
241#define BUCKETS 10000
242char *m_used[BUCKETS];
243char *m_used2[BUCKETS];
244
245VOID
246m_insert(cp) register char *cp; {
247    register int i;
248
249    if (disabled)
250        return;
251
252    for(i = 0; i < BUCKETS; i++)
253        if (m_used[i] == 0) {
254            m_used[i] = cp;
255            return;
256        }
257    disabled ++;
258}
259
260static VOID
261m_insert2(cp) register char *cp; {
262    register int i;
263
264    if (disabled)
265        return;
266    for(i = 0; i < BUCKETS; i++)
267        if (m_used2[i] == 0) {
268            m_used2[i] = cp;
269            return;
270        }
271    disabled ++;
272}
273
274int
275m_delete(cp) register char *cp; {
276    register int i;
277
278    for(i = 0; i < BUCKETS; i++)
279        if (m_used[i] == cp) {
280            m_used[i] = 0;
281            return(1);
282        }
283    for(i = 0; i < BUCKETS; i++)
284        if (m_used2[i] == cp) {
285            m_used2[i] = 0;
286            return(2);
287        }
288    if (disabled)
289        return(0);
290
291    maybe_quit("Freeing unmalloc'ed pointer");
292    return(0);
293}
294
295VOID
296m_init() {
297    register int i;
298
299    inited = 1;
300    disabled = 0;
301#ifdef NEXT
302    malloc_debug(2+4+8+16);
303#endif /* NEXT */
304
305    for(i = 0; i < BUCKETS; i++)
306      m_used[i] = 0;
307}
308
309VOID
310m_done() {
311    register int i,j=0;
312
313    if (disabled)
314        return;
315    for(i = 0; i < BUCKETS; i++)
316        if (m_used[i] != 0) {
317            if (memdebug) {
318                if (j == 0)
319                    fprintf(stderr,"unfree'ed buffers, indices: ");
320                fprintf(stderr,"%d, ", i);
321                j++;
322            }
323        }
324    if (j)
325        fprintf(stderr,"\n");
326    for(i = 0; i < BUCKETS; i++)
327        if (m_used2[i] != 0) {
328            if (memdebug) {
329                if (j == 0)
330                    fprintf(stderr,"unfree'ed registered buffers, indices: ");
331                fprintf(stderr,"%d, ", i);
332                j++;
333            }
334        }
335    if (j)
336        fprintf(stderr,"\n");
337    if (j)
338        maybe_quit("Unfree'ed malloc buffers");
339}
340
341VOID
342m_checkranges() {
343    int i;
344
345    for ( i = 0; i < BUCKETS; i++)
346        if (m_used[i])
347            check_range(m_used[i]);
348}
349
350static VOID
351maybe_quit(str) char *str; {
352    debug(F100,"mdebug maybe_quit","",0);
353    if (memdebug == 0)
354        return;
355    fprintf(stderr,"%s\n",str);
356    if (memdebug == 1)
357        abort();
358    if (memdebug == -1)
359        if (ask("Quit? "))
360            abort();
361}
362
363static int
364ask(str) char *str; {
365    char buf[100];
366    FILE *in;
367    int fd;
368
369    fd = dup(fileno(stdin));
370    in = fdopen(fd, "r");
371    while(1) {
372        fprintf(stderr,str);
373        fflush(stderr);
374        if (fgets(buf, 99, in) == NULL) /* EOF? */
375            return(0);
376        if (buf[0] == 'n' || buf[0] == 'N') {
377            fclose(in);
378            return(0);
379        }
380        if (buf[0] == 'y' || buf[0] == 'Y') {
381            fclose(in);
382            return(1);
383        }
384        fprintf(stderr,"please answer y/n.\n");
385    }
386}
387#endif /* MDEBUG */
Note: See TracBrowser for help on using the repository browser.