[comp.lang.c] how do you know 'free' freed?

howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) (10/13/89)

I've malloc'd a tree structure, and then free'd it, node by node.
Of course, freeing it just marks it as free, and I can still walk
through the tree after freeing it.  I'd like to confirm that it is
in fact free.

I tried malloc'ing an array after freeing the tree, but I can't 
tell the array where to go in memory, so the tree still seems to
be there.  There must be some way to confirm free.

On my sun3 (Unix 4.3 BSD, SunOS 4.0.3) my malloc man page says ther
is a function called mallocmap() which will print out the heap, but
I can't seem to find it.

Does anyone have some advice on this?

Mike Howard

cpcahil@virtech.UUCP (Conor P. Cahill) (10/13/89)

In article <5521@hacgate.UUCP>, howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) writes:
> I've malloc'd a tree structure, and then free'd it, node by node.
> Of course, freeing it just marks it as free, and I can still walk
> through the tree after freeing it.  I'd like to confirm that it is
> in fact free.


You could use the malloc tracing routines available on usenet in
comp.sources.unix/volume18/malloc-trace.Z.  Another thing you 
could do is to nullify each allocated data block before freeing
it.   That way you couldn't wall through the tree again.


-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

henry@utzoo.uucp (Henry Spencer) (10/13/89)

In article <5521@hacgate.UUCP> howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) writes:
>I've malloc'd a tree structure, and then free'd it, node by node.
>Of course, freeing it just marks it as free, and I can still walk
>through the tree after freeing it.  I'd like to confirm that it is
>in fact free.

You can sort-of do this by having your free-ing function clear the nodes
just before it frees them.  This is also a *wonderful* debugging aid,
because freed nodes never get mistaken for normal ones.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bph@buengc.BU.EDU (Blair P. Houghton) (10/14/89)

In article <5521@hacgate.UUCP> howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) writes:
>I've malloc'd a tree structure, and then free'd it, node by node.
>Of course, freeing it just marks it as free, and I can still walk
>through the tree after freeing it.  I'd like to confirm that it is
>in fact free.
>
>I tried malloc'ing an array after freeing the tree, but I can't 
>tell the array where to go in memory, so the tree still seems to
>be there.  There must be some way to confirm free.

Breeeeeep!

Assembler alert.

You don't have any right to expect any such thing of a computer
when you are programming in C.

Free() is, essentially, a convenience to the computer.  You're telling
it that it can clean up its act in case someone wants some more core
in the future.

"I can still walk through the tree after freeing it" is like saying
"I can still walk on the ice in april."  Yeah, you can, but you're
going to find that extra-thin patch long before you expect it, and
then you'll never say that again.

Not much else is defined about it.  Mostly it literally "frees" the
storage from the use of your program.  You can not use freed space
and legally expect it to work for you in any way.

Unfortunately, you also can't expect the system to do anything useful
with it like distill freed and unallocated space into a clean,
contiguous, allocatable block.  Luckily, they do, but you can't count
on it.

				--Blair
				  "The word 'undefined' comes up
				   unnervingly often in this business of
				   determinism and repeatability..."

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/14/89)

In article <5521@hacgate.UUCP> howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) writes:
>There must be some way to confirm free.

No, in general free() always works (assuming you have given it a valid
pointer that was malloc()ed) and there is no point in trying to see if
it worked.

gary@dgcad.SV.DG.COM (Gary Bridgewater) (10/16/89)

In article <11275@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <5521@hacgate.UUCP> howard@aic.dpl.scg.hac.com (Mike Howard (213)317-5690) writes:
>>There must be some way to confirm free.
>No, in general free() always works (assuming you have given it a valid
     ^^ ^^^^^^^
>pointer that was malloc()ed) and there is no point in trying to see if
                                  ^^^^^ ^^ ^^ ^^^^^
>it worked.

*BEEP*
Time's up. The original poster gave us the vital clue - Sun 4.0.something.
The correct answer is "malloc/free is somewhat broken in Sunos 4.0.1-3".
This has been mentioned before, in a Feb. Sun Spots article - here it is...

-=-=-=-=-=-=-==-=-
X-Sun-Spots-Digest: Volume 7, Issue 127, message 3 of 16

Fellow Spotters, I need your help.

A friend of mine has been developing a program which is a kind of
architectural CAD package.  Not being an architect, I'm not sure what one
might do with it, but it produces some pretty pictures in the process.
This program is having problems with malloc.

To start with, we are dealing with Sun 3's of various flavors, all with
color tubes.  They are running SunOS 3.4, using SunView, and SunCore.  The
programming is in C.

Malloc!!  Boy, what a mess.  Muses (the package mentioned above) maintains
a large number of linked lists, malloc'ing and free'ing space for nodes as
needed.  There is a LOT of malloc'ing and free'ing going on, and nodes
come in only a few sizes.  This last point is important.  Imagine the
following code fragment:

	node1 = malloc(N);
	node2 = malloc(N);
	free(node1);
	node3 = malloc(N);

Node3 does not get the memory which node1 released.  Instead, malloc asks
the system for additional memory to satisfy the malloc.  This is BUSTED!
Muses does a *****LOT***** of this, and grows and grows and grows in
memory, even though it may not need to.  Eventually, muses crashes, with
the program counter usually pointing into malloc.

I fetched the malloc replacement written by Bill Sebok at Princeton
University and plugged that in, but it didn't help tremendously because
something in SunCore and/or SunView seems to be calling variants of malloc
(calloc is one that comes to mind) and those suck up memory and crash.

Does anyone have a solution?  Upgrading to SunOS 4.0[.1] is not helpful
because the malloc problem still exists there.  In fact, here is a nice
little program which shows it.  (I sent in a bug report to sunbugs a day
or two ago, but haven't heard anything back.  Besides, I think we only
have update service, so they probably threw it into the trash.)

__________cut here for program
/*
 * NAME
 *	mtest - test memory allocation.
 *
 * COMPILATION
 *	cc -o mtest mtest.c
 *
 * SYNOPSIS
 *	mtest
 *
 * DESCRIPTION
 *	mtest demonstrates that malloc is broken.  Specifically, that
 *	malloc is not smart enough to use a piece of memory of exactly
 *	the right size when it is available (unless it is at the end
 *	of memory).
 */
#include <stdio.h>
#include <sys/errno.h>
#include <sys/types.h>

#define	BIGBUF		1000000	/* 1 MBytes */
#define SMALLBUF	10240	/* 10 KBytes */

char	*malloc();
caddr_t	sbrk();
extern int errno;

main()
{
	char	*buf1, *buf2;	/* buffer pointers */
	caddr_t	topmem;		/* upper limit of memory */

	printf("beginning memory allocation test\n");
	printf("All values are reported in decimal.\n");
	topmem = sbrk(0);
	printf("The end of memory is initially at %d\n\n",(int) topmem);

	/*
	 * Demonstrate that you can (sometimes) re-use memory which has
	 * been malloc'ed and subsequently free'd.
	 */
	buf1 = malloc(BIGBUF);
	if (buf1 == 0) {
		perror("test");
		errno = 0;
		exit(1);
	}
	else {
		printf("requested %d bytes of memory\n", BIGBUF);
		topmem = sbrk(0);
		printf("The end of memory is now at %d\n", (int) topmem);
	}

	if (free(buf1) == 0) {
		perror("test");
		errno = 0;
		exit(2);
	}
	else {
		printf("%d bytes of memory freed\n", BIGBUF);
		printf("There is now a %d byte piece of memory available.\n", BIGBUF);
		topmem = sbrk(0);
		printf("The end of memory is still at %d\n", (int) topmem);
	}

	buf1 = malloc(BIGBUF);
	if (buf1 == 0) {
		perror("test");
		errno = 0;
		exit(1);
	}
	else {
		printf("requested another %d bytes of memory -- ", BIGBUF);
		printf("Should use available space.\n");
		topmem = sbrk(0);
		printf("The end of memory is still at %d\n\n", (int) topmem);
	}

	/*
	 * Now demonstrate that if a block of free memory is surrounded
	 * by other chunks of memory, then a memory request of that size
	 * will NOT use the available piece.
	 */
	buf2 = malloc(SMALLBUF);
	if (buf2 == 0) {
		perror("test");
		errno = 0;
		exit(1);
	}
	else {
		printf("Requested %d bytes of memory.\n", SMALLBUF);
		topmem = sbrk(0);
		printf("The end of memory is now at %d\n", (int) topmem);
	}

	if (free(buf1) == 0) {
		perror("test");
		errno = 0;
		exit(2);
	}
	else {
		printf("Freed %d bytes of memory.\n", BIGBUF);
		printf("There is now a %d byte piece of memory available.\n", BIGBUF);
		topmem = sbrk(0);
		printf("The end of memory is still at %d\n", (int) topmem);
	}

	buf1 = malloc(BIGBUF);
	if (buf1 == 0) {
		perror("test");
		errno = 0;
		exit(1);
	}
	else {
		printf("Requested another %d bytes of memory -- ", BIGBUF);
		printf("Should use available space.\n");
		topmem = sbrk(0);
		printf("WHOA!  The end of memory is now at %d\n",(int) topmem);
	}

	exit(0);
}
__________cut here for program

Please email responses to me, it will be quicker than posting to
sun-spots.  I'll post a summary if anyone requests it.  In the mean time,
how can Sun, or any vendor, allow malloc and co. to be so busted?  It
boggles my mind.

William Reeder, University of Texas, Computation Center
ARPA: reeder@emx.utexas.edu	UUCP: ..!uunet!cs.utexas.edu!ut-emx!reeder
BITNET: CCCD001 @ UTA3081
-=-=-=-=-=-=-==-=-

And it's still that way in 4.0.3
-- 
Gary Bridgewater, Data General Corp., Sunnyvale Ca.
gary@sv4.ceo.sv.dg.com or 
{amdahl,aeras,amdcad,mas1,matra3}!dgcad.SV.DG.COM!gary
No good deed goes unpunished.

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/16/89)

In article <1175@svx.SV.DG.COM> gary@svx.SV.DG.COM () writes:
>The correct answer is "malloc/free is somewhat broken in Sunos 4.0.1-3".
>This has been mentioned before, in a Feb. Sun Spots article - here it is...

That sounds more like a "buddy system" allocator working normally.

chasm@attctc.Dallas.TX.US (Charles Marslett) (10/18/89)

In article <11313@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
.. In article <1175@svx.SV.DG.COM> gary@svx.SV.DG.COM () writes:
.. >The correct answer is "malloc/free is somewhat broken in Sunos 4.0.1-3".
.. >This has been mentioned before, in a Feb. Sun Spots article - here it is...
.. 
.. That sounds more like a "buddy system" allocator working normally.

If so, it also sounds like an excellent reason to disallow "buddy system"
allocators.

The purpose of malloc/calloc/et al. is to keep us from worrying about this
stuff -- if the allocator throws us traps, it better be easily bypassed.

Charles
===============================================================================
"Those who would sacrifice **  Charles Marslett
liberty for security,      **  STB Systems, Inc. <-- apply all std. disclaimers
deserve neither."          **  Wordmark Systems  <-- that's just me
  -- Benjamin Franklin     **  chasm\@attctc.dallas.tx.us
-------------------------------------------------------------------------------

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/19/89)

In article <9762@attctc.Dallas.TX.US> chasm@attctc.Dallas.TX.US (Charles Marslett) writes:
>If so, it also sounds like an excellent reason to disallow "buddy system"
>allocators.

Yes, and therefore you should complain loudly to the vendor that foists
one off on you.

Many BSD-based UNIX systems have a malloc() like this.  I don't like it
either.  The place to fix it, however, in in the C library, not in the
application.

djones@megatest.UUCP (Dave Jones) (10/21/89)

I didn't receive the article that the following refers to. I think it started
with <5521@hacgate.UUCP>. Can someone please fill me in on what this is all
about?

In article <9762@attctc.Dallas.TX.US> chasm@attctc.Dallas.TX.US (Charles Marslett) writes:
>If so, it also sounds like an excellent reason to disallow "buddy system"
>allocators.
>