From: ivanski@world.std.com (Ivan M CaveroBelaunde)
Subject: Re: DisposeHandle vs. ReleaseResource
Organization: The World Public Access UNIX, Brookline, MA
Date: Fri, 16 Oct 1992 04:13:33 GMT

system@asuvax.eas.asu.edu (Marc Lesure) writes:

>I have a routine that deletes, adds, and updates a resource in a
>preference file.  The function performs what it is suppose to do, however
>it doesn't seem to release the memory (if I call the routine enough times,
>it dies with a dsMemFullErr).  I understand that you need to use
>ReleaseResource(), if the allocated handle came from GetResource().  But
>what if the handle is created via a NewHandle() call?

Couple of problems here.  First of all, you don't need to call
ReleaseResource if you've removed it already from your resource map.
In fact, ReleaseResource will do nothing. Thus you need to call
DisposHandle.

Second, just to be on the safe side, you probably should SetResLoad(false)
before getting the resource you're removing. Otherwise you might get
NIL back from Get1Resource, not because it didn't find it, but because it
could not be loaded into memory.  If this happens, then you won't be
able to perform the AddResource properly (in fact, you'll end up with
two resources with the same type and ID in that file - a BAD thing).
Don't forget to SetResLoad(true) immediately after the Get1Resource.

>/* delete old resource */
	SetResLoad(false);
>	aH = Get1Resource(TYPE, baseID);
	SetResLoad(true);
>	if (aH != NIL)
>	{
>		RmveResource(aH);
>		UpdateResFile(resFile);
		DisposHandle(aH);
	/*	Do even if aH points to a purged handle to free the
		master pointer.	*/
/*	Comment out
>		ReleaseResource(aH);
*/
>		aH = NIL;
>	}

>/* add new resource */
>	if (aH == NIL)
>	{
>		aH = NewHandle(...);
>		if (aH == NIL)
>			return;
>		AddResource(aH, TYPE, baseID, NAME);
>	}

You might want to build this handle before toasting the old Prefs.
In general, I'd say it's bad form to nuke the old prefs and then be
unable to write out the new prefs because you were unable to allocate
space for the new prefs handle.
>	
>/* update resource */
>	if (ResError() == noErr)
>	{
>		HLock(aH);
>		... fill handle ...
>		HUnlock(aH);
>			
>		ChangedResource(aH);
>		WriteResource(aH);
>	}

>	ReleaseResource(aH); /* or DisposeHandle or Both? */

Just use release resource.

>	UseResFile(tmpResFile);
>	CloseResFile(resFile);

Your UseResFiles are a little mixed up. The only reason you'd need to do
the tempResFile bit at top is if the prefs res file was open in the first
place (if it's closed it'd become the current resFile when you open it,
so there would be no need to do UseResFile). If it was already open,
however, then you probably don't want to close it on exit.

Finally, it is also possible to do the following:
	Open the prefs file
	SetResLoad(false)
	prefH = Get1Resource(prefs)
	SetResLoad(true)
	if (!prefH) {
		newlyAdded = true;
		prefH = NewHandle()
		if (!prefH) return(MemError())
		AddResource(prefH, etc)
	} else newlyAdded = false;
	LoadResource(prefH)
	if (StripAddress(*prefH)) {
		fillPrefsHandle(prefH)
		ChangedResource(prefH)
		WriteResource(prefH)
	} else {
		RemoveResource(prefH)
		DisposHandle(prefH)
	}

Something like this would modify the prefs handle already in the resource
map. It seems a little cleaner, IMHO.

Hope this helps,

-Ivan
-----
Ivan Cavero Belaunde (ivanski@world.std.com)
DiVA Corporation
Newsgroups: comp.sys.mac.programmer