Category : Files from Magazines
Archive   : DDJ-9008.ZIP
Filename : SPENCER.LST

 
Output of file : SPENCER.LST contained in archive : DDJ-9008.ZIP
_DEBUGGING MEMORY ALLOCATION ERRORS_
by Lawerence D. Spencer


[LISTING ONE]

/* bad.c -- Mistakes in memory allocation */

#include
#include
#include

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
#include
#include

#include

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
#include
#include

#include

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
#include
#include

#include

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
#include
#include

#include

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
#include
#include
#include

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
#include
#include
#include

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
#include
#include
#include
#include

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
#include
#include

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
#include

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
#include
#include
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;
}
/*--------------------------------------------------------------------------*/



  3 Responses to “Category : Files from Magazines
Archive   : DDJ-9008.ZIP
Filename : SPENCER.LST

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/