naim@eecs.nwu.edu (Naim Abdullah) (09/09/88)
I want to check sections of a big program for memory leaks. My basic strategy was to define functions xmalloc() and xfree() that would keep track of the amount allocated, and to see if the amount went down to zero where it should (I wanted to use "#define malloc xmalloc" in the main header file to replace occurrences of malloc() and free()). The problem with this scheme is that I don't know how much space free() will actually free. Here is some sample code, illustrating what I mean: ===============================Cut Here============================ #include <stdio.h> extern char *malloc(); static unsigned int alloc_size = 0; char *xmalloc(size) unsigned int size; { char *p; if ((p = malloc(size)) != NULL) alloc_size += size; return p; } xfree(p) char *p; { unsigned int size_being_freed; size_being_freed = *((unsigned int *)(p - OFFSET)); /* probably wrong */ alloc_size -= size_being_freed; free(p); } unsigned int bytes_allocated() { return alloc_size; } main() { char *p1, *p2; p1 = xmalloc(10); p2 = xmalloc(99); xfree(p1); printf("%u bytes still allocated.\n", bytes_allocated()); } ===================================================================== Now, I don't know what to define OFFSET to be. I would like this to be portable between VAXen running 4.3bsd and Sun3s running SunOS 3.x, but if that is not possible, having it work on any one machine would be ok too. Any suggestions for the value of OFFSET or what the function xfree() should look like ? Thank you. Naim Abdullah Dept. of EECS, Northwestern University Internet: naim@eecs.nwu.edu Uucp: {oddjob, chinet, att}!nucsrl!naim P.S: There was a paper on "mprof" in the latest USENIX. That can be used to track down memory leaks as well as give you a lot of other information. Hopefully, it will be in the next BSD but until then,..
jeff@amsdsg.UUCP (Jeff Barr) (09/09/88)
In article <3950011@eecs.nwu.edu>, naim@eecs.nwu.edu (Naim Abdullah) writes: > I want to check sections of a big program for memory leaks. My basic > strategy was to define functions xmalloc() and xfree() that would keep > track of the amount allocated, and to see if the amount went down to > zero where it should (I wanted to use "#define malloc xmalloc" in the > main header file to replace occurrences of malloc() and free()). > > The problem with this scheme is that I don't know how much space free() > will actually free. You can allocate space for an extra 'int' in xmalloc, store the size yourself at the beginning of the allocated block (being sure to return a pointer PAST the 'int'), and then retrieve it in xfree. Jeff +---------------------------------------------------------+ | Jeff Barr AMS-DSG uunet!amsdsg!jeff 800-832-8668 | +---------------------------------------------------------+ -- Jeff +---------------------------------------------------------+ | Jeff Barr AMS-DSG uunet!amsdsg!jeff 800-832-8668 | +---------------------------------------------------------+
greggy@infmx.UUCP (greg yachuk) (09/10/88)
In article <3950011@eecs.nwu.edu> naim@eecs.nwu.edu (Naim Abdullah) writes: >Any suggestions for the value of OFFSET or what the function xfree() should >look like ? For both Sun and MSC, OFFSET is 2. I don't know about Vaxen, though > Naim Abdullah Greg Yachuk Informix Software Inc., Menlo Park, CA (415) 322-4100 {uunet,pyramid}!infmx!greggy why yes, I DID choose that login myself -------------------------------------------------------------------------------- Yes, yes hammerheads; swimming, kissing; we are big and clever and we don't know anything! God save hammerheads; keeping going; we are sleek and special, and we're sure of something
g-rh@cca.CCA.COM (Richard Harter) (09/10/88)
In article <3950011@eecs.nwu.edu> naim@eecs.nwu.edu (Naim Abdullah) writes: >I want to check sections of a big program for memory leaks. My basic >strategy was to define functions xmalloc() and xfree() that would keep >track of the amount allocated, and to see if the amount went down to >zero where it should (I wanted to use "#define malloc xmalloc" in the >main header file to replace occurrences of malloc() and free()). >The problem with this scheme is that I don't know how much space free() >will actually free. Here is some sample code, illustrating what I mean: If you merely want to know if the amount of space allocated has gone to zero a much simpler device is to maintain a counter in xmalloc/xfree. Increment every time you allocate space, decrement it every time you free it. The value of the counter at any time is the number of allocates for which there is no corresponding free. If this number is 0 there are no leaks. If you want more (i.e. you want to know where the leaks occur) you need to tie more information to the block. A quick and dirty way to do this is to allocate some extra space at the beginning of the block, two words for a doubly linked list, and one for an address. When you allocate a block link it into the list and load the address xmalloc was called from in the address field (it is easy to get this address, albeit in a machine dependent way). When you free the block delink it. The result is that the list gives you, at any time, a list of all addresses of calls to xmalloc of blocks that have not been deallocated. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
tps@chem.ucsd.edu (Tom Stockfisch) (09/11/88)
In article <164@amsdsg.UUCP> jeff@amsdsg.UUCP (Jeff Barr) writes: >In article <3950011@eecs.nwu.edu>, naim@eecs.nwu.edu (Naim Abdullah) writes: >> I want to check sections of a big program for memory leaks.... >You can allocate space for an extra 'int' in xmalloc, store the size >yourself at the beginning of the allocated block (being sure to return a >pointer PAST the 'int'), and then retrieve it in xfree. This assumes that "int" has the most stringent alignment requirements. Doesn't draft-ANS have a MAXALIGN_T or something like that? -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu
duane@cg-atla.UUCP (Andrew Duane) (09/12/88)
In article <3950011@eecs.nwu.edu>, naim@eecs.nwu.edu (Naim Abdullah) writes: > I want to check sections of a big program for memory leaks. My basic > strategy was to define functions xmalloc() and xfree() that would keep > track of the amount allocated, and to see if the amount went down to > zero where it should (I wanted to use "#define malloc xmalloc" in the > main header file to replace occurrences of malloc() and free()). In order to find memory leaks here, I wrote some routines to put into your program to track and report bad mallocs, bad frees, mallocs without frees, etc. The architecture of them is a new set of malloc/realloc/free routines that get spliced into your C library (using ar). The new routines generate entries into an audit file and then call the "real" routines (which are renamed). There are new calls added to start the audit file wherever you want, and to turn loggin on and off at will. Then, there is a separate program called NMPP (namelist postprocessor) which sifts through the audit file and generates a stack trace of the program at each point a malloc/free routine was called. It can weed out "properly matching" pairs, and just report the problems, or it can report all calls. The routines and programs run on a Sun-3, using SunOS 3.x. I don't know if they will run elsewhere (there is a little assembler "magic" to get the stack trace, and it relies on the format of the Sun stack frame). Andrew L. Duane (JOT-7) w:(508)-658-5600 X5993 h:(603)-434-7934 Compugraphic Corp. decvax!cg-atla!duane 200 Ballardvale St. ulowell/ \laidback Wilmington, Mass. 01887 cbosgd!ima/ \cgeuro Mail Stop 200II-3-5S ism780c/ \wizvax Only my cat shares my opinions, and she's breaking in the new help.
jfh@rpp386.Dallas.TX.US (The Beach Bum) (09/14/88)
In article <164@amsdsg.UUCP> jeff@amsdsg.UUCP (Jeff Barr) writes: >You can allocate space for an extra 'int' in xmalloc, store the size >yourself at the beginning of the allocated block (being sure to return a >pointer PAST the 'int'), and then retrieve it in xfree. the number of bytes being allocated and freed is not important. you need to keep a count of the number of memory regions which have been allocated and freed. another problem is keeping the allocated region maximally aligned. if you are using a system where doubles must be aligned modulo sizeof (double), allocating an int before the region will introduce alignment (and portability) problems. the pointer returned by malloc() can be cast to both a (double *) and a (char *). so, store the address of the region at the beginning of the region, then return the address of the double following the beginning of the region cast (void *). -- John F. Haugh II (jfh@rpp386.Dallas.TX.US) HASA, "S" Division "If the code and the comments disagree, then both are probably wrong." -- Norm Schryer
naim@eecs.nwu.edu (Naim Abdullah) (09/14/88)
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 <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); }