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=