tomc@mntgfx.MENTOR.COM (Tom Carstensen) (10/08/87)
Question: Do you need to HLock in the following kind of situation?: TEHandle TheText; lines = (**TheText).nLines :------------------------------------------------------------: : Tom Carstensen Usenet: tomc@mntgfx.MENTOR.COM : : Mentor Graphics GEnie: : :------------------------------------------------------------:
singer@endor.harvard.edu (Richard Siegel) (10/08/87)
In article <960@mntgfx.MENTOR.COM> tomc@mntgfx.MENTOR.COM (Tom Carstensen) writes: >Question: Do you need to HLock in the following >kind of situation?: > >TEHandle TheText; >lines = (**TheText).nLines No, since you're not calling a routine that might compact the heap, you're OK. Besides, you're double-dereferencing the handle, which is equally safe. --Rich **The opinions stated herein are my own opinions and do not necessarily represent the policies or opinions of my employer (THINK Technologies, Inc). * Richard M. Siegel | {decvax, ucbvax, sun}!harvard!endor!singer * * Customer Support | singer@endor.harvard.edu * * THINK Technologies, Inc. (No snappy quote) *
fry@huma1.HARVARD.EDU (David Fry) (10/08/87)
In article <960@mntgfx.MENTOR.COM> tomc@mntgfx.MENTOR.COM (Tom Carstensen) writes: >Question: Do you need to HLock in the following >kind of situation?: > >TEHandle TheText; >lines = (**TheText).nLines No, because you're only accessing memory and assigning it to a stack variable, lines. You need to HLock when memory may be moved. Inside Mac has a list of Toolbox calls that can move memory, but if you don't want to look it up you can call HLock before a Toolbox routine (better to look it up). Suppose, however that you wanted to create a NewWindow and the refcon was going to be the number of lines in the TEHandle, then you must HLock before calling the NewWindow because NewWindow may move memory: MoveHHi(TheText); HLock(TheText); myWindow = NewWindow( , ,...,(**TheText).nLines ); HUnlock(TheText); "How to Write Macintosh Software" by Scott Kastner (sp?) is a great source for tidbits like this. David Fry fry@huma1.harvard.EDU Department of Mathematics fry@harvma1.bitnet Harvard University ...!harvard!huma1!fry Cambridge, MA 02138
oster@dewey.soe.berkeley.edu (David Phillip Oster) (10/08/87)
In article <960@mntgfx.MENTOR.COM> tomc@mntgfx.MENTOR.COM (Tom Carstensen) writes: >Question: Do you need to HLock in the following kind of situation?: >TEHandle TheText; >lines = (**TheText).nLines No. Here is a simple rule: Always lock handles if you pass a pointer to any part of the data of the handle to a procedure or system call. Unlock them as soon as possible so the memory manager can do a better job. Assume handles are unlocked. Remember, resources might be purgable, and the same conditions that cause handle data to move may also cause purgable resources to be flushed. Here is an example: PicHandle foo; foo = GetResource('PICT', 128); /* get the handle */ HLock(foo); /* passing address of part of foo's contents */ DrawPicture(foo, &(**foo).picFrame); HUnlock(foo); ... /* some later use of foo */ LoadResource(foo); /* foo is a resource. It might have been purged */ -------- versus PicHandle foo; Rect r; foo = GetResource('PICT', 128); /* get the handle */ r = (**foo).picFrame; /* copy the frame */ HNoPurge(foo); /* foo is a resource! */ DrawPicture(foo, &r); /* no lock needed */ HPurge(foo); ---------- The rule above ("any procedure call or op sys call") errs on the side of conservatism for a number of reasons: Suppose you are calling something that you _know_ does not rearrange the heap. You could be wrong for the following reasons: 1.) As the operating system changes, op. sys. that don't do heap scrambles today may tomorrow. 2.) As your program grows and changes, functions you call today may do heap scrambles tomorrow. 3.) The operating system call you may require assembly language glue, which might be in another CODE segment. The procedure you are calling today might get moved to another CODE segement as the program grows and changes. Loading code segments into memory causes heap scrambles. If you are conservative with your HLocks(), it will make your programs run less effiecently. Extraneous Lock/UnLocks in our programs cost us a whole 5 milliseconds every month! The alternative is La Bomba, or days spent debugging. I know which I'd rather choose. Pascal is particularly nasty. Pascal has these things called "Var parameters" that are like the C "pass the address with '&'" except there is no way for you to tell by reading a function call whether the compiler is going to pass the address of a variable or its value. I spoke with Bill Atkinson at the first Hacker's Conference and he said that unlocked handles across function calls was the _costliest_ source of bugs when he was debugging MacPaint. He said that the way he caught them was to use the DA "Monkey", which generates random key and mouse events. The first time he thought MacPaint was done, Monkey crashed it in under 5 minutes. The version shipped with the first macs had survived 2 weeks under the Monkey. (Consumer note: If you value your files, do not run Monkey on your hard disk.) --- David Phillip Oster --A Sun 3/60 makes a poor Macintosh II. Arpa: oster@dewey.soe.berkeley.edu --A Macintosh II makes a poor Sun 3/60. Uucp: {uwvax,decvax,ihnp4}!ucbvax!oster%dewey.soe.berkeley.edu
oster@dewey.soe.berkeley.edu (David Phillip Oster) (10/08/87)
In article <2961@husc6.UUCP> fry@huma1.UUCP (David Fry) writes: >Suppose, however that you wanted to create a NewWindow and the >refcon was going to be the number of lines in the TEHandle, >then you must HLock before calling the NewWindow because >NewWindow may move memory: > MoveHHi(TheText); > HLock(TheText); > myWindow = NewWindow( , ,...,(**TheText).nLines ); > HUnlock(TheText); Wrong. The arguments of a function are fully evaluated before the function gets called. (**TheText).nLines evaluates to an Integer, and integers are passed by value in C. Now if you had said (**TheText).lineStarts then you would have been correct, since arrays are passed by reference in C. The address of the lineStarts array would be computed, NewWindow would get called, shuffle memory, and the address would be bogus by the time NewWindow got around to using it.
mday@cgl.ucsf.edu (Mark Day) (10/09/87)
In article <21204@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes: >I spoke with Bill Atkinson at the first Hacker's Conference and he >said that unlocked handles across function calls was the _costliest_ >source of bugs when he was debugging MacPaint. He said that the way he >caught them was to use the DA "Monkey", which generates random key and >mouse events. The first time he thought MacPaint was done, Monkey >crashed it in under 5 minutes. The version shipped with the first macs >had survived 2 weeks under the Monkey. (Consumer note: If you value >your files, do not run Monkey on your hard disk.) > I have heard of many references to this mythical Monkey DA, yet I haven't seen it on any billboards. Can someone give me/the net an idea where we can get it, so we can use it to crash our programs too. ---------- Mark Day UUCP: ..ucbvax!ucsfcgl!mday ARPA: mday@cgl.ucsf.edu BITNET: mday@ucsfcgl.BITNET
jww@sdcsvax.UCSD.EDU (Joel West) (10/09/87)
In article <21206@ucbvax.BERKELEY.EDU>, oster@dewey.soe.berkeley.edu (David Phillip Oster) writes: > The arguments of a function are fully evaluated before the function > gets called. (**TheText).nLines evaluates to an Integer, and integers are > passed by value in C. Of course, Pascal programs have to be careful to watch out for VAR parameters, since VAR parameters are passed by reference and the block might have relocated by the time the procedure call completes and it's time to store the value. In C, it's a little safer (one of the few times it is) since you see the parameter being passed as &foo (by reference.) Or rather, you hopefully saw that it was a VAR parameter and remembered to pass it by reference (my favorite Mac C gotcha!) -- Joel West (c/o UCSD) Palomar Software, Inc., P.O. Box 2635, Vista, CA 92083 {ucbvax,ihnp4}!sdcsvax!jww jww@sdcsvax.ucsd.edu So. California: where the ground does the Rocking 'N Rolling for you
bob@lznh.UUCP (<10000>Bob Lemley) (10/15/87)
In article <960@mntgfx.MENTOR.COM>, tomc@mntgfx.MENTOR.COM (Tom Carstensen) writes: > Question: Do you need to HLock in the following > kind of situation?: > > TEHandle TheText; > lines = (**TheText).nLines Answer: No, but be sure to allocate memory space for the TextEdit record via TENew() before accessing any fields of the TE record. Usually, you lock handles down only if you are both: 1) dereferencing the handle AND 2) making a call to a routine which may purge or move memory. For example, if you passed the address of an ELEMENT contained in an unlocked heap structure to a subroutine and the subroutine made a toolbox call that moved memory, the pointer you passed could become invalid (ie. point to garbage, or worse, to important system data). Usually, you should call MoveHHi after locking a handle to avoid heap fragmentation problems. Inside Mac contains an appendix of all ToolBox and OS routines which might purge or move memory. Robert C. Lemley { ihnp4 | allegra } lznh!bob
bob@lznh.UUCP (<10000>Bob Lemley) (10/15/87)
> In article <2961@husc6.UUCP>, fry@huma1.HARVARD.EDU (David Fry) writes: >> In article <960@mntgfx.MENTOR.COM> tomc@mntgfx.MENTOR.COM (Tom Carstensen) writes: > >Question: Do you need to HLock in the following [ excess removed ] > MoveHHi(TheText); > HLock(TheText); > myWindow = NewWindow( , ,...,(**TheText).nLines ); > HUnlock(TheText); HLock is not required here because the dereferencing is done BEFORE the JSR to NewWindow.