[comp.sys.mac.programmer] Problems every programmer gets

ksitze@nmsu.edu (360) (08/17/89)

In article: <alex@rata.vuw.ac.nz's message of 14 Aug 89 22:03:12 GMT>
Alex Heatly is complaining about random crashes during LSP compilation
or execution of a project.

In answer, there are several possible causes behind the mentioned
problems.

Most probable cause:
    You are allocating a handle (pointer) in one section of your
program, maybe use it for a bit and put it in storage.  Some other
piece of your program takes that stored handle, uses it for a while
and after finished with it, deallocates the handle.  If the handle is
not overwritten with a nil after being deallocated, it still points to
the released master pointer.  Now, if your program tries to use this
handle elsewhere (and even checks for nil handles) it will use an
invalid handle and write out into memory Apple-knows-where.  Enough
times and you could shot code or data out from just about anything,
including your LSP environment.

Other (related) problems that you may have and not know of...

Take the program below:

program SampleCode;

  type
    myTmpHdl = ^myTmpPtr;
    myTmpPtr = ^myTmpRec;
    myTmpRec = record
      TEHdl : TEHandle;
      data  : Handle;
      dLen  : longint;		{ notice I'm being 32-bit clean? }
    end;

procedure ReleaseTmp( myTmp : myTmpHdl );
begin
  with myTmp^^ do
    begin
      TEDispose( TEHdl );
      DisposHandle( data );
    end;
  DisposHandle( Handle(myTmp) );
  myTmp = nil;
end;

function AllocateTmp : myTmpHdl;
var
  dst, view : Rect;
  myTmp : myTmpHdl;
  port : GrafPtr;
begin
  myTmp = myTmpHdl(NewHandle(sizeof(myTmpRec)));
  if myTmp <> nil then
    begin
      GetPort(port);
      dst = port^.portRect;
      view = port^.portRect;
      myTmp^^.TEHdl = TENew(dst, view);	{ Proper code should even check }
      myTmp^^.data = NewHandle(0);	{ these values here. }
      myTmp^^.dLen = 0;
    end;
end;

var
  myTHdl : myTmpHdl;

begin
  {....initialization....}
  myTHdl = AllocateTmp;
  {....Do some stuff with myTHdl here....}
  if (some condition) then
    ReleaseTmp(myTHdl);
  {....Do something else for a while....}
  if myTHdl<>nil then
    begin 
      {....use the data in myTHdl here....}
    end;
end.

Now, nothing seems to be wrong here does it (besides some syntax)?
Sure, everything will work just fine if the if statement evaluates to
'FALSE'.  But what happens when it is 'TRUE'?  'myTHdl' is deallocated
in ReleaseTmp, ReleaseTmp sets it to nil and everything is hunky-dory
right?  Wrong.  ReleaseTmp sets the local myTmp to nil but since myTmp
is not a variable parameter, myTHdl is left with the old value.
Easily fixed by inserting the word 'var' before myTmp in ReleaseTmp.
This trick is especially bad when ReleaseTmp is declared in the
interface part of a unit as you tend to not check the original
procedure declaration.  This one has caught me several times, it seems
so simple that no one would ever do it, but it happens.

With a program that had a similar problem to the one above, I had
problems that sounded much like those described in the article by
Alex.

Other possible problems:
  Assuming that calls such as 'NewHandle', 'NewPtr', 'GetResource' etc
always return valid handles/pointers.
  Leaving the original values in just deallocated handles/pointers as
this makes it difficult to track down handle/pointer illegal
references.  Always writing nil into these variables makes life so
much easier.
  Leaving values on the stack (this is hard to do in LSP but possible
if you directly manipulate the stack)
  Not checking potential nil handles/pointers when they're used.  Not
necessary usually if you check the return values from NewHandle and
such but should be done if the handle/pointer could possibly be
deallocated before your code uses it.
  Any of those listed in TN212 (The joy of being 32-bit clean).

Hope that something in here is useful to someone out there...

					-Kelesi
--
+--------------------------------------------------------------------+
| From the Macintosh of: Kevin L. Sitze. This is ME: ksitze@NMSU.edu |
+------------------------------------------------------+-------------+
| The difference between intelligence and stupidity is |   Is this   |
| that intelligence has a limit.          -- anonymous |   better?   |
+------------------------------------------------------+-------------+