/* Smartalloc.c Copyright Clinton Staley 1991 * * Smartalloc provides an malloc version which checks for several possible * errors: * * 1. Failure of malloc call for any reason * 2. Attempt to free memory not allocated by malloc, or already freed. * 3. Writing past the end of malloc-ed memory * 4. Failure to free memory by some point in the program. * 5. Use of data after it has been freed. * * Use smartalloc by including smartalloc.h in any file that calls malloc * or free. Also, compile smartalloc.c along with your other .c files. * If you make any of errors 1-3 above, smartalloc will report the error * and the file/line on which it occured. To find out if you have left * memory unfreed, call report_space(). If any unfreed memory is * outstanding, report_space will report the number of bytes of unfreed * memory. If no memory is unfreed, report_space remains silent. * Use of freed data is "detected" by writing garbage into the freed data, * which will usually generate a runtime fault if the data is later used. * * All rights to this package are reserved by its author. Duplication of * source or object code is permitted only with the author's permission. */ #include #include #define PATTERN 0xA #define TAIL_BYTES 4 typedef struct track_t { char *data; int space; struct track_t *next; } track_t; static track_t *track = NULL; static int allocated = 0; char *smartalloc(long bytes, char *file, int line) { track_t *temp; char *data; int i; temp = (track_t *) malloc(sizeof(track_t)); if ((temp->data = data = malloc(bytes + TAIL_BYTES)) == NULL) fprintf(stderr, "Malloc failure in file %s on line %d\n", file, line); allocated += bytes; for (i = 0; i < TAIL_BYTES; i++) data[bytes + i] = PATTERN; temp->space = bytes; temp->next = track; track = temp; return data; } void smartfree(char *address, char *file, int line) { track_t *temp, *to_free; int i; if (track == NULL) { fprintf(stderr, "Attempt to free non-malloced space in file %s at line %d\n", file, line); return; } if (track->data == address) { to_free = track; track = track->next; } else { for (temp = track; temp->next != NULL && temp->next->data != address;) temp = temp->next; if (temp->next == NULL) { fprintf(stderr, "Attempt to free non-malloced space in file %s at line %d\n", file, line); return; } to_free = temp->next; temp->next = to_free->next; } for (i = 0; i < TAIL_BYTES; i++) if (address[to_free->space + i] != PATTERN) { fprintf(stderr, "Space freed in file %s at line %d has data written past its end.\n", file, line); break; } for (i = 0; i < to_free->space; i++) address[i] = PATTERN; allocated -= to_free->space; free(address); free(to_free); } int report_space() { if (allocated > 0) fprintf(stderr, "Allocated space is %d\n", allocated); }