[comp.sys.amiga.tech] How much does FreeMem ?

page@swan.ulowell.edu (Bob Page) (03/24/88)

Arrggh..

I did some poking around & found out that yes, it does work in 8-byte
chunks.  Seems logical, since that's how AllocMem() works.

I never checked the memory list after my call to FreeMem() ... turns
out that it was not being changed at all!  Kinda strange, but who
knows what evil lurks in the heart of DOS.

It also means this code that looks so pretty and is commented so well
will never work.  I still _want_ it to work.  If I run the program
once or twice, and never touch it after that, I can work for days with
no problems.

Ah well.

..Bob
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
		"Nicaragua" is Spanish for "Vietnam."

cmcmanis%pepper@Sun.COM (Chuck McManis) (03/24/88)

This is a great question, mostly because I think I know the answer :-),
but partly because the answer isn't documented *anywhere*.

In article <5650@swan.ulowell.edu> page@swan.ulowell.edu (Bob Page) writes:
>The RKM states that AllocMem() will round your byte request up to the
>next 8-byte boundary (and says don't count on this).
>
>The autodocs say FreeMem() will free space that you've allocated.
>Does it also round up to the nearest 8 bytes? 

Definitely YES. FreeMem() and AllocMem() calculate how many bytes you
really have by the same formula so as long as you don't lie to it about
those sizes you are safe. (If you allocate a 16 byte chunk and try to 
free it in 16 one byte chunks it is guru city.)

>The FreeMem() doc says/implies that it must be my memory, or at least
>something that was allocated in some system-nice way.

This is correct so far ...

>That is, I'm copying a DOS list to my own list, pointing DOS at it,
>then deallocating the old list.  I know you're all shaking, saying
>"don't you DARE deallocate one of DOS's lists!" but I think I'm doing
>it in a very safe way, and don't think the stuff in this list is
>contained anywhere else, like in DOS's stack or anything.

/**** Save this you DOS hackers out there *******/

Ah but here is the kicker, DOS doesn't use AllocMem() to get it's memory!
Turns out, (and I found this out when trying to debug my Assign.c program
and which Andy Finkel later verified by presumably looking at the source...)
DOS allocates memory with two constraints, 1) The memory allocated is an
even number of long words (multiple of 4 bytes), *AND* puts the length in 
bytes into the long word *before* the address it returns. So lets say 
you allocate 6 bytes for an Assign, you could do it like this

ULONG *
DOSmalloc(size)

int size;
{
	ULONG	*A;

	A = (ULONG *)AllocMem((size+7)/4);
	*A = (size+7)/4
	return(A+1);
}

Now this is included in Arp (DOSAlloc() and DOSFree()). The nice part 
of this scheme is that DOSFree can be the macro 
#define DOSFree(p)	FreeMem((ULONG *)(p)-1,*((ULONG *)(p)-1))

Which uses the length previously stored in memory. 
Make you DOS lists with memory allocated in this fashion and your
Amiga will stop crashing when you play with DOS lists.


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.