2 C K C M D B . C -- malloc debugger.
6 Author: Howie Kaye, Columbia University Center for Computing Activities.
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.
13 /* Use the real ones in this module! */
32 _PROTOTYP ( FILE * fdopen, (int, char *) );
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).
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.
54 #define M_SIZE_T size_t
57 #define M_SIZE_T unsigned
65 _PROTOTYP( void free, (void *) );
66 _PROTOTYP( void * malloc, (size_t) );
67 _PROTOTYP( void * realloc, (void *, size_t) );
69 _PROTOTYP( VOID free, (char *) );
70 _PROTOTYP( char * malloc, (M_SIZE_T) );
71 _PROTOTYP( char * realloc, (char *, M_SIZE_T) );
74 _PROTOTYP( VOID m_insert, (char *) );
75 _PROTOTYP( int m_delete, (char *) );
77 _PROTOTYP( char * dmalloc, (int) );
78 _PROTOTYP( char * dcalloc, (int, int) );
79 _PROTOTYP( char * drealloc, (char *, int) );
81 _PROTOTYP( char *set_range_check, (char *, int) );
82 _PROTOTYP( char *check_range, (char *) );
83 _PROTOTYP( static char *maybe_check_range, (char *) );
85 _PROTOTYP( static VOID maybe_quit, (char *) );
86 _PROTOTYP( static int ask, (char *) );
89 #define min(x,y) ((x) < (y) ? (x) : (y))
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)
99 dmalloc(size) int size; {
102 cp = malloc(size + RSIZE + INTSIZE);
104 cp = set_range_check(cp, size);
111 dcalloc(nelem, elsize) int nelem, elsize; {
114 cp = dmalloc(nelem * elsize);
116 memset(cp, 0, nelem * elsize);
121 drealloc(bp,size) char *bp; int size; {
125 maybe_quit("Freeing NULL pointer");
128 cp = check_range(bp);
130 cp = realloc(cp, size + RSIZE + INTSIZE);
132 cp = set_range_check(cp, size);
139 dfree(cp) char *cp; {
141 maybe_quit("Freeing NULL pointer");
143 switch(m_delete(cp)) {
145 cp = maybe_check_range(cp);
148 cp = check_range(cp);
156 #endif /* CK_ANSIC */
160 set_range_check(cp,size) char *cp; int size; {
164 for(i = 0; i < INTSIZE; i++) { /* set the size in the string */
168 cp += INTSIZE; /* skip the size */
170 for(i = 0; i < RFRONT; i++) /* set the front of the range check */
171 cp[i] = RANGE[i]; /* string */
173 cp += RFRONT; /* skip the front range check */
175 for(i = 0; i < RBACK; i++) /* set the back odf the range check */
176 cp[i+size] = RANGE[i+RFRONT];
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.
186 check_range(cp) char *cp; {
187 register char *bp = cp - RFRONT - INTSIZE;
192 for(i = 0 ; i < INTSIZE; i++) { /* get the size out of the string */
194 size |= bp[INTSIZE-i-1] & 0xff;
198 for(i = 0; i < RFRONT; i++) /* check front range check */
199 if (bp[i] != RANGE[i]) {
200 maybe_quit("leftside malloc buffer overrun");
203 bp += RFRONT; /* skip front range check */
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");
214 maybe_check_range(cp) char *cp; {
215 register char *bp = cp - RFRONT - INTSIZE;
220 for(i = 0 ; i < INTSIZE; i++) { /* get the size out of the string */
222 size |= bp[INTSIZE-i-1] & 0xff;
226 for(i = 0; i < RFRONT; i++) /* check front range check */
227 if (bp[i] != RANGE[i]) {
230 bp += RFRONT; /* skip front range check */
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");
241 #define BUCKETS 10000
242 char *m_used[BUCKETS];
243 char *m_used2[BUCKETS];
246 m_insert(cp) register char *cp; {
252 for(i = 0; i < BUCKETS; i++)
253 if (m_used[i] == 0) {
261 m_insert2(cp) register char *cp; {
266 for(i = 0; i < BUCKETS; i++)
267 if (m_used2[i] == 0) {
275 m_delete(cp) register char *cp; {
278 for(i = 0; i < BUCKETS; i++)
279 if (m_used[i] == cp) {
283 for(i = 0; i < BUCKETS; i++)
284 if (m_used2[i] == cp) {
291 maybe_quit("Freeing unmalloc'ed pointer");
302 malloc_debug(2+4+8+16);
305 for(i = 0; i < BUCKETS; i++)
315 for(i = 0; i < BUCKETS; i++)
316 if (m_used[i] != 0) {
319 fprintf(stderr,"unfree'ed buffers, indices: ");
320 fprintf(stderr,"%d, ", i);
325 fprintf(stderr,"\n");
326 for(i = 0; i < BUCKETS; i++)
327 if (m_used2[i] != 0) {
330 fprintf(stderr,"unfree'ed registered buffers, indices: ");
331 fprintf(stderr,"%d, ", i);
336 fprintf(stderr,"\n");
338 maybe_quit("Unfree'ed malloc buffers");
345 for ( i = 0; i < BUCKETS; i++)
347 check_range(m_used[i]);
351 maybe_quit(str) char *str; {
352 debug(F100,"mdebug maybe_quit","",0);
355 fprintf(stderr,"%s\n",str);
364 ask(str) char *str; {
369 fd = dup(fileno(stdin));
370 in = fdopen(fd, "r");
374 if (fgets(buf, 99, in) == NULL) /* EOF? */
376 if (buf[0] == 'n' || buf[0] == 'N') {
380 if (buf[0] == 'y' || buf[0] == 'Y') {
384 fprintf(stderr,"please answer y/n.\n");