home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
08
/
spencer.lst
< prev
next >
Wrap
File List
|
1990-06-20
|
11KB
|
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;
}
/*--------------------------------------------------------------------------*/