[comp.sys.mac.programmer] HLock and Think C 4.0

Mats.Sundvall@bio.embnet.se (11/18/89)

Just got bit by not locking a handle!

Please correct me if I am totally wrong but this is what I think happend.
But my diagnose raised a couple of questions.

In Think C 4.0 I define an object CTime as a instance of CObject. It has some
integer fields and one Str255 field. The method Setstring does a strcpy
from the parameter to the field.

So I compile and run the program, the first time I does a CList::Setstring
the string is empty. The second time the string is there.

When tracing the code I notice that the memory location for CList->mystring
is moved, probably because the ANSI library is moved into memory.
So I do a HLock on the CTime object and unlock it after I have done the
strcpy. It works.

Then I locked through the object library to see if this is the method that
Think uses. I was surprised when I did not find that many HLock in their
code. One difference when they copy strings is that they copy pstrings
with CopyPString (that does a Blockmove). Is it safe to do a Blockmove
without locking the handle? I would expect that many more HLocks should be in
the code.

	Mats Sundvall
	University of Uppsala
	Sweden

jnh@ecemwl.ncsu.edu (Joseph N. Hall) (11/18/89)

In article <18.25645e4f@bio.embnet.se> Mats.Sundvall@bio.embnet.se writes:
>Just got bit by not locking a handle!
>
>In Think C 4.0 I define an object CTime as a instance of CObject. It has some
>integer fields and one Str255 field. The method Setstring does a strcpy
>from the parameter to the field. ...

Happened almost exactly like that to me.  A good general rule of thumb is
that in any situation where you use a dereferenced object member as an argument
to a library function (i.e., libfoo(foo->mbr)) you should HLock(foo) before
making the call.  "foo" in this case frequently turns out to be "this".

I'm not sure I like this "feature" of the THINK OOP system.  I wish there
were some "safety glue" or something that the compiler could insert in
these situations to do most or all of this handle locking for you ...
v   v sssss|| joseph hall                      || 4116 Brewster Drive
 v v s   s || jnh@ecemwl.ncsu.edu (Internet)   || Raleigh, NC  27606
  v   sss  || SP Software/CAD Tool Developer, Mac Hacker and Keyboardist
-----------|| Disclaimer: NCSU may not share my views, but is welcome to.

vallon@sbcs.sunysb.edu (Justin Vallon) (11/21/89)

In article <18.25645e4f@bio.embnet.se> Mats.Sundvall@bio.embnet.se writes:
>Just got bit by not locking a handle!
>[Creates an object in TC4.0, which uses handles, that contains a string]
>[Fails first time, works second]
>[First time, the segment is loaded and the handle is moved, second not]
>
>Then I locked through the object library to see if this is the method that
>Think uses. I was surprised when I did not find that many HLock in their
>code. One difference when they copy strings is that they copy pstrings
>with CopyPString (that does a Blockmove). Is it safe to do a Blockmove
>without locking the handle? I would expect that many more HLocks should be in
>the code.

Yes, it is safe to do a BlockMove without locking the handle.  One of IM's
appendicies is a list of routines that move/purge memory.  BlockMove isn't
in it, so you can use it without locking.

However, you seem to have discovered the problem.  The first call to your
ANSI library causes a LoadSeg (see Segment Loader for details), since the
library (is presumably) in an unloaded segment.  Notice that LoadSeg is in
the list of routines that may move/purge memory.  Memory is moved, and the
address to your string is now pointing into never-never land.  The second
call succeeds because the segment has been loaded, and LoadSeg is not
called.

Solution:  (1)  Make sure that all "safe" routines (ie:  ones that do not
move/purge memory) are always loaded.  This insures that a disasterous
LoadSeg is not called when you are vulnerable.  (2)  Be paranoid, and
Lock everything all the time.  This sort of defeats the purpose, and it's
sort of like stopping at a green light, just in case.

(1) is probably a better solution.  I usually leave the libraries in the
main segment, so that stuff like this doesn't happen.

>	Mats Sundvall
>	University of Uppsala
>	Sweden

-Justin
vallon@sbcs.sunysb.edu

ech@cbnewsk.ATT.COM (ned.horvath) (11/24/89)

From article <3997@sbcs.sunysb.edu>, by vallon@sbcs.sunysb.edu (Justin Vallon):

! Yes, it is safe to do a BlockMove without locking the handle.  One of IM's
! appendicies is a list of routines that move/purge memory.  BlockMove isn't
! in it, so you can use it without locking.
! 
! However, you seem to have discovered the problem.  The first call to your
! ANSI library causes a LoadSeg (see Segment Loader for details), since the
! library (is presumably) in an unloaded segment.  Notice that LoadSeg is in
! the list of routines that may move/purge memory.  Memory is moved, and the
! address to your string is now pointing into never-never land.  The second
! call succeeds because the segment has been loaded, and LoadSeg is not
! called.

! Solution:  (1)  Make sure that all "safe" routines (ie:  ones that do not
! move/purge memory) are always loaded.  This insures that a disasterous
! LoadSeg is not called when you are vulnerable.  (2)  Be paranoid, and
! Lock everything all the time.  This sort of defeats the purpose, and it's
! sort of like stopping at a green light, just in case.

! (1) is probably a better solution.  I usually leave the libraries in the
! main segment, so that stuff like this doesn't happen.

This is difficult when linked with the full ANSI library in TC4 (around 24K
I think).  However, it is very sensible to preload the segment(s) containing
MacTraps and ANSI.  You can do this explicitly: touch the library, select
the Get Info command, and note the segment number.  In ResEdit, open the 
built application, open CODE, touch the segment, and do a Get Info.  Set
the Preload bit.

An indirect method is to simply make a call on the library early, and never
UnloadSeg any library segment.  A dummy BlockMove call would appear to do it!

=Ned Horvath=