[comp.unix.wizards] malloc

spier@madison.steinmetz (kevin l spier) (08/10/88)

Hi -

I am new to this group so please bear with me if this question
has been asked and answered before. 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.

None of the calls to calloc() return a NULL pointer so it doesn't seem
that this has anything to do with running out of virtual memory (btw, the
total amount of memory being requested is always < 1 Mbyte).  I am also
assuming that a segmentation fault is not a standard error
notification for malloc().

This problem occurs on both a SUN 2 and Sequent Balance 21000 running
SUNOS 3.4 and Dynix 3.0.4 (both 4.2 bsd derivatives) respectively. I
tried using malloc_debug() on the Suns but it was very flaky giving
inconsistent reports on the heap's state.

Is this a known problem with malloc() for bsd 4.2 derivatives? 
If anyone has any suggestions on how to go about correcting, working
around, and/or isolating this problem [like a pd allocator which has
good diagnostics] please let me know.

Thank you.

Kevin L. Spier
spierk@turing.cs.rpi.edu

ditto@cbmvax.UUCP (Michael "Ford" Ditto) (08/11/88)

In article <11812@steinmetz.ge.com> spierk@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@kenobi.cts.com
This space under construction,		...!ucsd!elgar!ford
pardon our dust.			ditto@cbmvax.commodore.com