Tracking Memory Leaks (summary + code)

Naim Abdullah naim at eecs.nwu.edu
Wed Sep 14 18:13:42 AEST 1988


A couple of days ago I asked how to detect memory leaks (not
free'ing what you had malloc'ed earlier). My question was how
to write functions xmalloc() and xfree() which could replace the
calls to malloc() and free().

Many people replied with samples of code and suggestions. My thanks
to all of you. There were two basic approaches suggested:

1) Look at the header of the malloc'ed block to get the size.
   This is what I was (unsuccessfully) trying to do in the code 
   I posted. People pointed out that the size allocated by
   malloc() might be greater than what you asked for, so the correct
   thing to do in xmalloc() is:
   
	alloc_size += *((unsigned int *)(p-sizeof(int)));

   and in xfree 

	size_being_freed = *((unsigned int *)(p - sizeof(int)));
	
   The disadvantage of this approach is that it is not portable
 and might fail if your malloc() has been compiled with error checking.
 (The above works on stock 4.3bsd and SunOS 3.5). The advantage of this
 approach is that no extra memory is used.
 
2) Ask the real malloc for the size being asked plus 4 extra bytes. Store
the size in an int at the beginning of the block, advance the pointer by
four bytes and return it to the caller.

   In free(), back up the pointer by four bytes and get the number stored
there as the size of the block. Give this pointer to the real free() to
free the block.

   I feel this approach is very elegant. Using it, I was able to find the
memory leak I was looking for.

   Here is some code from Karl Heuer (karl at haddock.isc.com). It implements
xmalloc(), xcalloc(), xfree(), xrealloc() and bytes_allocated(). Karl
gave me permission to post this so you may want to put it in your
toolbox.

		      Naim Abdullah
		      Dept. of EECS,
		      Northwestern University

		      Internet: naim at eecs.nwu.edu
		      Uucp: {oddjob, chinet, att}!nucsrl!naim
============================Cut Here==================================
#define ALIGN   8       /* system-dependent; may need to be tuned */
#define SLOP    ((sizeof(size_t)+ALIGN-1)/ALIGN*ALIGN)

#if defined(__STDC__)
#include <stddef.h>
#include <stdlib.h>
#define Void    void
#else
#define NULL    0
#define Void    char
extern Void *malloc();
extern Void *realloc();
extern Void *calloc();
extern void  free();
typedef unsigned int size_t;
#endif

static size_t alloc_size = 0;

Void *xmalloc(size) size_t size; {
    Void *p = malloc(SLOP + size);
    if (p != NULL) {
        *(size_t *)p = size;
        alloc_size += size;
        p = (Void *)((char *)p + SLOP);
    }
    return (p);
}

Void *xcalloc(nmemb, size) size_t nmemb; size_t size; {
    Void *p = calloc(SLOP + (size *= nmemb), 1);
    if (p != NULL) {
        *(size_t *)p = size;
        alloc_size += size;
        p = (Void *)((char *)p + SLOP);
    }
    return (p);
}

void xfree(p) Void *p; {
    if (p != NULL) {
        p = (Void *)((char *)p - SLOP);
        alloc_size -= *(size_t *)p;
    }
    free(p);
}

Void *xrealloc(p, newsize) Void *p; size_t newsize; {
    if (p != NULL) {
        p = (Void *)((char *)p - SLOP);
        alloc_size -= *(size_t *)p;
    }
    p = realloc(p, SLOP + newsize);
    if (p != NULL) {
        *(size_t *)p = newsize;
        alloc_size += newsize;
        p = (Void *)((char *)p + SLOP);
    }
    return (p);
}

size_t bytes_allocated() {
    return (alloc_size);
}

/* Now to test it */

#include <stdio.h>
main() {
    Void *p1, *p2;
    p1 = xmalloc(10);
    p2 = xmalloc(99);
    xfree(p1);
    printf("%lu bytes still allocated\n", (unsigned long)bytes_allocated());
    return (0);
}



More information about the Comp.lang.c mailing list