[comp.lang.c] memory allocation problems

asbury@nprdc.navy.mil (Mike Asbury) (12/29/90)

HELP!  I have a large program (over 100,000 lines of code) written in Turbo C
with memory leakage somewhere.  I am looking for any programs that will help me 
find C memory allocation errors.  Any pointers to shareware or commercial 
programs will be appreciated.  
					Thanks in advance,
					Mike

gordon@osiris.cso.uiuc.edu (John Gordon) (12/30/90)

	Well, here is a product that looks like its just what you need:

	Bounds-Checker by Nu-Mega Technologies, Inc.

	The ad says that it helps in solving "pointer problems and other out-
of-bounds memory accesses".

	You can find a copy of the ad in pretty much any issue of Dr. Dobb's
magazine.  (Look for an ad with a picture of a penguin.)

	Bounds-Checker
	Nu-Mega Technologies, Inc
	P.O. Box 7780
	Nashua, NH 03060-7780
	(603) 888-2386
	FAX (603) 888-2465

	I'm not endorsing or recommending this product, I'm just answering
the question.


---
John Gordon
Internet: gordon@osiris.cso.uiuc.edu        #include <disclaimer.h>
          gordon@cerl.cecer.army.mil       #include <clever_saying.h>

tada@athena.mit.edu (Michael J Zehr) (12/31/90)

Someone wrote:
> [help -- memory leak!!]

What I do is use allocation/deallocation macros something like:

#define _new(type) (type *)malloc_debug(sizeof(type), __FILE__, __LINE__)

and a similar one for free.  then in malloc_debug and free_debug i have
code that writes the pointer being allocated/freed with the file name
and line number to a log file.  (making sure the pointer is at the same
position in each line.)

because the pointers are at the same position you can do a sort on the
log file and collect all the lines regarding a particular memory
location together... (it should be a stable sort so if the same location
is returned more than once by malloc you can still sort out the file.)

then it should be pretty clear which mallocs have no associated frees.

the set of #defines above are #ifdef-ed to something like DEBUG so you
can compile without the extra overhead once you're sure there aren't any
memory leaks.

(i've used this to find memory leaks in 20,000 line programs in 5
minutes.  *much* easier than poring over code or something like that.)

-michael j zehr
software engineer
consultants for management decisions, inc.

bryan@stiatl.UUCP (Bryan Donaldson) (01/04/91)

gordon@osiris.cso.uiuc.edu (John Gordon) writes:
>	Well, here is a product that looks like its just what you need:
>	Bounds-Checker by Nu-Mega Technologies, Inc.
>	The ad says that it helps in solving "pointer problems and other out-
>of-bounds memory accesses".


Unfortunately, Bounds-Checker does not check dynamically allocated 
memory space. We got the program to check our software, but as 60 to
90 % of the memory used in dynamically allocated, it wasn't very
useful.

BGD

rwskubowius@spurge.uwaterloo.ca (Rog Skubowius) (01/18/91)

In article <11589@arctic.nprdc.navy.mil> asbury@nprdc.navy.mil (Mike Asbury) writes:
>HELP!  I have a large program (over 100,000 lines of code) written in Turbo C
>with memory leakage somewhere.  I am looking for any programs that will help me 
>find C memory allocation errors.  Any pointers to shareware or commercial 
>programs will be appreciated.  
>					Thanks in advance,
>					Mike

	My first question to you is whether or not you have any function 
	calls 'farmalloc(), farfree(), or farrealloc()'? Also, what version
	of the compiler are you using? If it is Turbo C++ v.1.0, the problem
	may not be yours. I found a bug in their farrealloc() call when
	I was asking for about 650K of total memory. The screen memory
	is overwritten by Turbo as it thinks this is valid 'usable' memory.
	Anyway, back to your problem. I encourage you to write 3 ( or
	possibly 6 ) routines, 1 per C dynamic function routine. For
	instance, CheckMalloc(), CheckFree(), CheckRealloc(). If you
	use a prefixing ( & possibly postfixing ) signature on the allocated
	buffer, & embed the buffer size as well, you can easily fix this
	problem & find the bug. Let me show this:

	unsigned short CheckMalloc( void ** buffer, unsigned short size )
	{
		The application on top of CheckMalloc() wants 'size' bytes,
		but instead, now call malloc() for 'size' + say 3. Then, write
		the letters 'foo' in the first 3 bytes of the allocated memory
		& assign (*buffer) to the next byte following the 'foo' signature.

		fooXXXXXXXXX	-> where a pointer to the 1st X is returned 
						-> through (*buffer) to the calling function.

	}

	void CheckFree( void * buffer )
	{
		Now, if the application has corrupted the buffer, you can
		determine it here. You see, *(buffer - 3) == 'f', 
		*(buffer - 2) == 'o', *(buffer - 1) == 'o'. You should really
		macro the checking signature, its length and then use 
		strncpy() to do the checking of signature. Anyway, if this
		doesn't check out...bang...you've caught some memory corruption
		as either the original 'CheckMalloc()'d pointer was moved, or
		someone overwrote part of your buffer.
	}

	CheckRealloc()
	{
		Pretty obvious what to do here --> Check out the signature 
		& act accordingly.
	}

	This whole scheme can be improved by using a signature at the
	start & one at the end as well, and then putting the allocated
	buffer size in the buffer itself so that the end of application
	buffer & start of end signature can be found. Dig?   

paulh@cognos.UUCP (Paul Hays) (01/18/91)

In article <11589@arctic.nprdc.navy.mil> asbury@nprdc.navy.mil (Mike Asbury) writes:
>HELP!  I have a large program (over 100,000 lines of code) written in Turbo C
>with memory leakage somewhere.  I am looking for any programs that will help me 
>find C memory allocation errors.  Any pointers to shareware or commercial 
>programs will be appreciated.  
>					Thanks in advance,
>					Mike

In article <1991Jan18.000814.15191@watdragon.waterloo.edu> rwskubowius@spurge.uwaterloo.ca (Rog Skubowius) writes:
>
>	               ...            I encourage you to write 3 ( or
>	possibly 6 ) routines, 1 per C dynamic function routine. For
>	instance, CheckMalloc(), CheckFree(), CheckRealloc(). If you
>	use a prefixing ( & possibly postfixing ) signature on the allocated
                        ^^^^^^^^ ^^^^^^^^^^
Always: many arena corruptors seem to scribble on the upper signature.

>	buffer, & embed the buffer size as well, you can easily fix this
>	problem & find the bug. Let me show this:
>
>	unsigned short CheckMalloc( void ** buffer, unsigned short size )
>	{
>		The application on top of CheckMalloc() wants 'size' bytes,
>		but instead, now call malloc() for 'size' + say 3. Then, write

The number of additional bytes is critical in some applications;
the buffer must be aligned on many mahines.

>		the letters 'foo' in the first 3 bytes of the allocated memory
>		& assign (*buffer) to the next byte following the 'foo' signature.
>
>		fooXXXXXXXXX	-> where a pointer to the 1st X is returned 
>						-> through (*buffer) to the calling function.
>
>	}
>
>	void CheckFree( void * buffer )
>	{
>		Now, if the application has corrupted the buffer, you can
>		determine it here. You see, *(buffer - 3) == 'f', 
>		*(buffer - 2) == 'o', *(buffer - 1) == 'o'. You should really
>		macro the checking signature, its length and then use 
>		strncpy() to do the checking of signature. Anyway, if this
>		doesn't check out...bang...you've caught some memory corruption
>		as either the original 'CheckMalloc()'d pointer was moved, or
>		someone overwrote part of your buffer.
>	}
    [etc.]

We use a shell around the malloc() routine as well; mine is specified
to match the C library routine with additional side effects:
    - The allocator returns a 'char *' (hey, it's pre-ANSI).
    - The signature below the returned address is large enough to
      ensure that the address is suitably aligned for an object
      of any type. (This 8 bytes for the RISC machines.)
    - The allocator saves information used for automatic checking.

This code is only linked into development versions of the programs
because of the overhead (see below). For the release version, the
C preprocessor is used to substitute the actual C library routines:
    #define mallocph(s) malloc(s)    /* use C library allocator */

These routines get very serious about detecting corruption of the
arena. The module that defines the checking routines also defines
a large static array of structs used to track the
status of each block allocated. Each block gets
a serial number that is recorded in its struct, along with the block's
size and address. (The checking routines keep only 'signature' bytes
in the allocated space; everything else is in the array. After all,
we're looking for arena corrupters ...)

Whenever any block is allocated, reallocated, or freed, an internal
routine scans the static array and checks all of the signatures
at the bottom and top of each block.

It seems that many corruptors call the routines strcat(), strncpy(),
memset(), memcpy(), and the like to scribble on the arena for them.
The latest incarnation of the checker includes shells for these
routines as well; the shell routines call the C library routine
and then test to see whether it misbehaved.

Amazingly, the overhead for all of this checking has not proven to
be a problem even in programs which use the arena excessively.
-- 
Paul Hays                Cognos Incorporated     S-mail: P.O. Box 9707
Voice: (613) 738-1338 ext 3804                           3755 Riverside Drive 
  FAX: (613) 738-0002                                    Ottawa, Ontario 
 uucp: uunet!mitel!cunews!cognos!paulh                   CANADA  K1G 3Z4