Path: utzoo!attcan!uunet!husc6!uwvax!oddjob!tank!nucsrl!naim From: naim@eecs.nwu.edu (Naim Abdullah) Newsgroups: comp.lang.c Subject: Tracking Memory Leaks (summary + code) Message-ID: <3950012@eecs.nwu.edu> Date: 14 Sep 88 08:13:42 GMT Organization: Northwestern U, Evanston IL, USA Lines: 124 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@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@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 #include #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 main() { Void *p1, *p2; p1 = xmalloc(10); p2 = xmalloc(99); xfree(p1); printf("%lu bytes still allocated\n", (unsigned long)bytes_allocated()); return (0); }