home *** CD-ROM | disk | FTP | other *** search
File List | 1990-06-20 | 10.6 KB | 402 lines |
- _DEBUGGING MEMORY ALLOCATION ERRORS_
- by Lawerence D. Spencer
-
-
- [LISTING ONE]
-
- /* bad.c -- Mistakes in memory allocation */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
-
- main()
- {
- char *allocated_but_never_freed;
- char *this_one_is_ok;
- char *freed_but_never_allocated;
-
- allocated_but_never_freed = malloc(10);
- this_one_is_ok = malloc(20);
-
- free(this_one_is_ok);
- free(freed_but_never_allocated);
-
- return(0);
- }
-
-
- [LISTING TWO]
-
- /* bad.c -- Mistakes in memory allocation */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
-
- #include <mem.h>
-
- main()
- {
- char *allocated_but_never_freed;
- char *this_one_is_ok;
- char *freed_but_never_allocated;
-
- allocated_but_never_freed = memMalloc(10,"tag 1");
- this_one_is_ok = memMalloc(20,"tag 2");
-
- memFree(this_one_is_ok, "tag 3");
- memFree(freed_but_never_allocated,"tag 4");
-
- return(0);
- }
-
-
-
- [LISTING THREE]
-
- /* memMalloc() -- Same as malloc(), but registers activity using memTrack().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
-
- #include <mem.h>
-
- void *memMalloc(size_t bytes, char *tag)
- {
- void *allocated;
- allocated = malloc(bytes);
- memTrack_alloc(allocated, tag);
- return(allocated);
- }
-
- /* memFree() -- Same as free(), but registers activity using memTrack().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
-
- #include <mem.h>
-
- void memFree(void *to_free, char *tag)
- {
- if (memTrack_free(to_free, tag))
- {
- free(to_free);
- }
- }
- /* MEMTRACK.C -- Module to track memory allocations and frees that occur
- * in the other mem...() routines. Global routines:
- * memTrack_alloc() -- Records allocations.
- * memTrack_free() -- Records attempts to free.
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
-
- #include <mem.h>
-
- static FILE *memTrack_fp(void);
- static void memTrack_msg(char *msg);
-
- #define ALLOC 'A'
- #define FREE 'F'
-
- /* Track an allocation. Write it in the debugging file in the format
- * A 0000:0000 tag */
- void memTrack_alloc(void *allocated, char *tag)
- {
- FILE *fp;
-
- if (fp = memTrack_fp())
- {
- fseek(fp,0L,SEEK_END);
- fprintf(fp,"%c %p %s\n",ALLOC, allocated, tag);
- fclose(fp);
- }
- }
-
- /* Track freeing of pointer. Return FALSE if was not allocated, but tracking
- * file exists. Return TRUE otherwise. */
- int memTrack_free(void *to_free, char *tag)
- {
- int rc = 1;
- FILE *fp;
- void *addr_in_file = 0;
- #define MAX_LTH 200
- char line[MAX_LTH];
- char found = 0;
- char dummy;
- int ii;
- long loc;
- if (fp = memTrack_fp())
- {
- rewind(fp);
- for ( loc=0L; fgets(line,MAX_LTH,fp); loc = ftell(fp) )
- {
- if (line[0] != ALLOC) /* Is the line an 'Allocated' line? */
- continue; /* If not, back to top of loop. */
- ii = sscanf(line,"%c %p",&dummy, &addr_in_file);
- if (ii==0 || ii==EOF)
- continue;
- /* Is addr in file the one we want? */
- if ( (char *)addr_in_file - (char *)to_free == 0 )
- {
- found = 1;
- fseek(fp,loc,SEEK_SET); /* Back to start of line */
- fputc(FREE,fp); /* Over-write the ALLOC tag */
- break;
- }
- }
- fclose(fp);
- if (!found)
- {
- char msg[80];
- sprintf(msg,"Tried to free %p (%s). Not allocated.",to_free,tag);
- memTrack_msg(msg);
- }
- }
- return(rc);
- }
-
- /* Return FILE pointer for tracking file. */
- static FILE *memTrack_fp()
- {
- static char *ep = NULL; /* Points to environment var that names file */
- FILE *fp = NULL; /* File pointer to return */
-
- if (ep == NULL /* First time through, just create blank file */
- && (ep = getenv("MEMTRACK"))
- && (fp = fopen(ep,"w")) )
- {
- fclose(fp);
- fp = 0;
- }
- if (ep) /* If we have a file name, proceed. */
- { /* Otherwise, do nothing. */
- fp = fopen(ep,"r+"); /* Open debugging file for append access. */
- if (!fp)
- {
- fprintf(stderr,"\a\nCannot open %s\n\a",ep);
- }
- }
- return(fp);
- }
-
- /* Write a message to the debugging file. */
- static void memTrack_msg(char *msg)
- {
- FILE *fp;
-
- if (fp = memTrack_fp())
- {
- fseek(fp,0L,SEEK_END);
- fprintf(fp,"\n%s\n",msg);
- fclose(fp);
- }
- else
- {
- fprintf(stderr,"%s\n",msg);
- }
- }
-
- /* memCalloc() -- Same as calloc(), but registers activity using memTrack().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
- #include <mem.h>
-
- void *memCalloc(size_t num_elems, size_t bytes_per_elem, char *tag)
- {
- void *allocated;
- allocated = calloc(num_elems, bytes_per_elem);
- memTrack_alloc(allocated, tag);
- return(allocated);
- }
-
- /* memRealloc() - Same as realloc(), but registers activity with memTrack().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
- #include <mem.h>
-
- void *memRealloc(void *allocated, size_t bytes, char *tag)
- {
- memTrack_free(allocated, tag);
- allocated = realloc(allocated, bytes);
- if (allocated)
- {
- memTrack_alloc(allocated, tag);
- }
- return(allocated);
- }
-
- /* memStrdup() -- Same as strdup(), but registers activity using memTrack().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <malloc.h>
- #include <string.h>
- #include <mem.h>
-
- void *memStrdup(void *string, char *tag)
- {
- void *allocated;
- allocated = strdup(string);
- memTrack_alloc(allocated, tag);
- return(allocated);
- }
-
-
-
- [LISTING FOUR]
-
-
- /* MEM.H -- ** Copyright (c) 1990, Cornerstone Systems Group, Inc. */
-
- #ifdef MEMTRACK
-
- void *memCalloc(size_t num_elems, size_t bytes_per_elem, char *tag);
- void memFree(void *vp, char *tag);
- void *memMalloc(size_t bytes, char *tag);
- void *memRealloc(void *oldloc, size_t newbytes, char *tag);
- void *memStrdup(void *string, char *tag);
- /* The next two functions are only called by the other mem functions */
- void memTrack_alloc(void *vp, char *tag);
- int memTrack_free(void *vp, char *tag);
- #else
- #define memCalloc(NUM,BYTES_EACH,TAG) calloc(NUM,BYTES_EACH)
- #define memFree(POINTER,TAG) free(POINTER)
- #define memMalloc(BYTES,TAG) malloc(BYTES)
- #define memRealloc(OLD_POINTER,BYTES,TAG) realloc(OLD_POINTER,BYTES)
- #define memStrdup(STRING, TAG) strdup(STRING)
- #endif
-
-
- [LISTING FIVE]
-
- /* DEMOHEAP.C - Demonstrate use of heap...() functions.
- * Copyright (c) 1990 - Cornerstone Systems Group, Inc.
- */
-
- #include <stdio.h>
- #include <malloc.h>
- #include <heap.h>
-
- static void my_own_msg_func(char *msg);
-
- main()
- {
- char *allocated_but_never_freed;
- char *this_one_is_ok;
- char *freed_but_never_allocated;
- heapPrt_set_msg_func(my_own_msg_func);
- allocated_but_never_freed = malloc(10);
- heapPrt("after first malloc()");
- this_one_is_ok = malloc(20);
- heapPrt("after second malloc()");
- free(this_one_is_ok);
- heapPrt("after first free()");
- free(freed_but_never_allocated);
- heapPrt("after second free()");
- return(0);
- }
-
- /* heapPrt() makes its report with puts() by default. This will not be
- * appropriate for some applications, so we will demonstrate the use of an
- * alternative message function. This one writes to stderr.
- * The alternative function should take one argument (a char *). Its
- * return value is ignored, so it might as well be void.
- */
- static void my_own_msg_func(char *msg)
- {
- fprintf(stderr,"My own message function: %s\n",msg);
- }
- OUTPUT:
- My own message function: 1 allocations, 10 bytes, after first malloc()
- My own message function: 2 allocations, 30 bytes, after second malloc()
- My own message function: 1 allocations, 10 bytes, after first free()
- My own message function: 1 allocations, 10 bytes, after second free()
-
-
- [LISTING SIX]
-
- /* heap.h - Header file for use with heap...() functions.
- * Copyright (c) 1990 - Cornerstone Systems Group, Inc.
- */
-
- void heapPrt(char *tag);
- void heapPrt_set_msg_func(void (*new_msg_func)() );
- void heapUsed(unsigned int *numused, long *totbytes);
-
- /* HEAPUSED.C -- Tell how much of heap has been used. For use with MS C 5.x
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
- #include <malloc.h>
- #include <heap.h>
-
- void heapUsed(
- unsigned int *numused,
- long *totbytes)
- {
- struct _heapinfo hinfo;
- int status;
- *numused = 0;
- *totbytes = 0L;
- hinfo._pentry = (char *)0;
- while ( (status=_heapwalk(&hinfo)) == _HEAPOK)
- {
- if (hinfo._useflag == _USEDENTRY)
- {
- ++ (*numused);
- *totbytes += hinfo._size;
- }
- }
- }
-
- /* HEAPPRT.C -- Print summary information about heap. For use with MS C 5.x
- * This module contains two functions:
- * heapPrt() prints the summary information.
- * heapPrt_set_msg_func() allows you to specify a function for heapPrt()
- * to use, other than printf().
- * Copyright (c) 1990, Cornerstone Systems Group, Inc.
- */
- #include <stdio.h>
- #include <malloc.h>
- #include <heap.h>
- static void (*heapPrt_msg_func)() = 0;
-
- /*--------------------------------------------------------------------------*/
- void heapPrt(
- char *tag) /* Description of where you are in processing */
- {
- unsigned int numused; /* Number of allocations used */
- long totbytes; /* Total bytes allocated */
- char msg[80]; /* Message to display */
- heapUsed(&numused, &totbytes);
- if (!heapPrt_msg_func)
- heapPrt_msg_func = puts;
- sprintf(msg, "%5u allocations, %6ld bytes, %s",numused,totbytes,tag);
- heapPrt_msg_func(msg);
- }
- /*--------------------------------------------------------------------------*/
- void heapPrt_set_msg_func(
- void (*new_msg_func)())
- {
- heapPrt_msg_func = new_msg_func;
- }
- /*--------------------------------------------------------------------------*/
-