|
|
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.