malloc() problems...

Michael "Ford" Ditto ditto at cbmvax.UUCP
Thu Aug 11 06:59:45 AEST 1988


In article <11812 at steinmetz.ge.com> spierk at turing.cs.rpi.edu writes:
>                                    I have two pieces of C code
>written independently of each other which are having similar problems
>with malloc() [actually they call calloc() and never malloc()
>directly]. The problem is that after allocating memory without problem
>yet another call is made to calloc(). Calloc() in turn calls malloc()
>which dies with a segmentation violation.  This behavior occurs at
>different points in each of these two pieces of code, but occurs
>consistently for each piece.

This is the most common symptom of a corrupt memory free list, which is
caused by one of three things:

	1)	Freeing memory (with free()) which is not currently
		allocated.  This includes passing a null ponter to
		free() or free()ing the same block too many times.

	2)	Overrunning the boudaries of an allocated block of
		memory.  This is usually in the form of writing off
		the end of your block because you didn't request as
		many bytes as you really need.

	3)	A bug in the malloc package.  Persue this option
		last, as it's almost always the least likely.

Note that both of the types of errors that you, the programmer, can
make will NOT result in any sort of error UNTIL THE NEXT TIME YOU
CALL MALLOC.  (Some versions of free() can also die if the list is
corrupt, but usually it's the next malloc() that dies.)

Here's a trick you can do to help track down malloc problems:
I typed it in from memory, so there's NO warrantee...

	extern char *malloc();

	#define	MYMAGIC 0x2a /* Just some unlikely bit pattern */

	char *mymalloc(nbytes)
	unsigned nbytes;
	{
		char *ptr = malloc(nbytes+9);
		if (!ptr)
		{
			fprintf(stderr, "mymalloc returning 0\n");
			return ptr;
		}
		*((unsigned *)ptr) = nbytes;
		ptr += 8;
		ptr[-1] = MYMAGIC;
		ptr[nbytes] = MYMAGIC;
		fprintf(stderr, "mymalloc returning 0x%lx\n", (long)ptr);
		return ptr;
	}

	void myfree(ptr)
	char *ptr;
	{
		unsigned nbytes;
		fprintf(stderr, "myfree freeing 0x%lx\n", (long)ptr);
		nbytes = *((unsigned *)(ptr-8));
		if (ptr[-1] != MYMAGIC | ptr[nbytes] != MYMAGIC)
			fprintf(stderr, " (Freeing corrupt block!)\n");
		free(ptr-8);
	}

	#define	malloc	mymalloc
	#define	free	myfree


Put the above code in a header file and #include it if you want to
enable the "verbose malloc".  Redirect stderr to a file so you can
study the messages.  Here is an example output:

	mymalloc returning 0x180c
	mymalloc returning 0x182c
	myfree freeing 0x180c
	myfree freeing 0x182c
	 (Freeing corrupt block!)
	myfree freeing 0x180c
	mymalloc returning 0x400c

As you can see in this example, there were two errors found.  The second
block malloced was corrupt when it was freed, and the first block was
freed twice.  Also, a potential error is that the third block was NEVER
freed, although this might be OK if the program intentionally exited
with that memory still allocated.

I have used this technique many times to track down some pretty
obscure bugs; it's not fun but it's often the only way.
-- 
					-=] Ford [=-

	.		.		(In Real Life: Mike Ditto)
.	    :	       ,		ford at kenobi.cts.com
This space under construction,		...!ucsd!elgar!ford
pardon our dust.			ditto at cbmvax.commodore.com



More information about the Comp.unix.wizards mailing list