mikeoro@hubcap.clemson.edu (Michael K O'Rourke) (12/16/89)
I know this has been discussed before, but could someone tell me when it is necessary to use HLock? If i have a handle within a CDEF do i need to do so? What if i only access the handle thru a pointer, i.e. : void doSomething(theControl) ControlHandle theControl; { ControlPtr cp; cp = *theControl; if (cp->contrlRect ...... and so on....... Thanks, Michael
6500stom@hub.UUCP (12/16/89)
> I know this has been discussed before, but could someone tell me when > it is necessary to use HLock? If i have a handle within a CDEF do i need > to do so? What if i only access the handle thru a pointer, i.e. : > > void doSomething(theControl) > ControlHandle theControl; > { > ControlPtr cp; > > cp = *theControl; > if (cp->contrlRect ...... and so on....... It doesn't matter whether you dereference it or not in C. You might as well have done (**theControl).contrlRect instead of cp->contrlRect. The way to remember if you need to lock your handle is if you pass a field in the handle to any procedure that might move memory--even if its one of your own routines in a different segment. For example, if you do RectRgn(myRgn, (**theControl).contrlRect) you need to lock theControl down because RectRgn might move the handle before its done with the contrlRect. / Josh Pritikin T Ignorance is bliss. \ | Mail: 6500stom@ucsbuxa.ucsb.edu | I must be in hell. | | AppleLink: Josh.P | My room is proof that entropy | \ GEnie: J.Pritikin ! exists. /
6600pete@hub.UUCP (12/16/89)
From article <3331@hub.UUCP>, by 6500stom@hub.UUCP (): > The way to remember if you need to lock your handle is if you pass > a field in the handle to any procedure that might move memory--even > if its one of your own routines in a different segment. Oh, Joshling, I can't bear it. I tell you how to post and immediately you go spreading misinformation! :-) DTS' official position now is that there are so many patched traps running around calling the Memory Manager that you need to lock and unlock handles around ANY trap call. The list, in other words, is no longer valid. For the record, the following situations involve locked handles: passing elements of records pointed to by dereferenced handles as Pascal "var" parameters assigning return values from function-style traps to elements of records pointed to by dereferenced handles inside Pascal "with" statements which include handles in the "with" Can anyone think of any other situations? ------------------------------------------------------------------------------- Pete Gontier | InterNet: 6600pete@ucsbuxa.ucsb.edu, BitNet: 6600pete@ucsbuxa Editor, Macker | Online Macintosh Programming Journal; mail for subscription Hire this kid | Mac, DOS, C, Pascal, asm, excellent communication skills
tim@hoptoad.uucp (Tim Maroney) (12/17/89)
In article <3331@hub.UUCP> 6500stom@hub.UUCP writes: >> I know this has been discussed before, but could someone tell me when >> it is necessary to use HLock? If i have a handle within a CDEF do i need >> to do so? What if i only access the handle thru a pointer, i.e. : >> >> ControlPtr cp; >> cp = *theControl; >> if (cp->contrlRect ...... and so on....... > >It doesn't matter whether you dereference it or not in C. You might >as well have done (**theControl).contrlRect instead of cp->contrlRect. Sort of. I would never do this, and I strongly recommend against it. As soon as anything happens which could move memory, cp becomes an invalid pointer, and has to be refreshed from theControl. It would be awfully easy to forget this; it's asking for errors which wouldn't happen if you always used (*theControl)-> instead of cp-> . So, when do you need to lock down handles? Very rarely. You cited the main case, Josh: >The way to remember if you need to lock your handle is if you pass >a field in the handle to any procedure that might move memory--even >if its one of your own routines in a different segment. >For example, if you do >RectRgn(myRgn, (**theControl).contrlRect) you need to lock theControl >down because RectRgn might move the handle before its done with the >contrlRect. Another case, which some people may remember I posted an ill-considered flame about a few months ago, is: (*marsup)->wombat = NewHandle(WOMBAT_SIZE); The compiler is free to evaluate the address of the left-hand side before it performs the right-hand side. If NewHandle moves memory, then its return value will be assigned into outer space. However, I don't like to lock handles when it can be easily avoided. I would do your case without locking by using a temp variable, and the same for my case. Rect r; r = (*theControl)->contrlRect; RectRgn(myRgn, &r); and Handle h = NewHandle(WOMBAT_SIZE); (*marsup)->wombat = h; Slightly more stack overhead, but you avoid trap overhead for locking and unlocking, and also avoid all the state-restoration hassles that have been mentioned lately here. One final point: heap scramble mode in a debugger, while very slow, is excellent at discovering when you have not respected handle dereferencing issues. It is a good idea to do as complete a test run as you can stand under heap scramble every few weeks or even days. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com "Our newest idol, the Superman, celebrating the death of godhead, may be younger than the hills; but he is as old as the shepherds." - Shaw, "On Diabolonian Ethics"
freek@fwi.uva.nl (Freek Wiedijk) (12/17/89)
In article <3332@hub.UUCP> 6600pete@hub.UUCP writes: >DTS' official position now is that there are so many patched traps running >around calling the Memory Manager that you need to lock and unlock handles >around ANY trap call. The list, in other words, is no longer valid. You mean that nowadays even BlockMove moves memory? :-) I would think that if I patch a trap that may NOT move memory, and that patch moves memory, then that patch has a bug! -- Freek "the Pistol Major" Wiedijk Path: uunet!fwi.uva.nl!freek #P:+/ = #+/P?*+/ = i<<*+/P?*+/ = +/i<<**P?*+/ = +/(i<<*P?)*+/ = +/+/(i<<*P?)**
omullarn@oracle.oracle.com (Oliver Mullarney) (12/19/89)
In article <9313@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: > >Rect r; >r = (*theControl)->contrlRect; >RectRgn(myRgn, &r); > as a way of avoiding using HLock and HUnlock. Not in this case. What you are handing to RectRgn is a pointer into a relocatable block. It may look like a legitimate pointer, but it is not, so this *can* crap out. HLock and HUnlock are probably the best solution in this case, or the HGetState and HSetState calls. | Oliver Mullarney | "I have knowledge of Digital Watches, and soon I | | Oracle Corporation | shall have knowledge of Video Cassette Recorders" | | omullarn@oracle.com | Time Bandits | --------------- "Universally acknowledged to work just fine" ---------------- | Oliver Mullarney | "I have knowledge of Digital Watches, and soon I | | Oracle Corporation | shall have knowledge of Video Cassette Recorders" | | omullarn@oracle.com | Time Bandits | --------------- "Universally acknowledged to work just fine" ----------------
6600pete@hub.UUCP (12/19/89)
From article <292@fwi.uva.nl>, by freek@fwi.uva.nl (Freek Wiedijk): > I would think that if I patch a trap that may NOT move memory, and that > patch moves memory, then that patch has a bug! I agree. Unfortunately, work-arounds are a fact of life. Fortunately, this particular work-around doesn't introduce any more kludgy behavior, as work-arounds are wont to do. ------------------------------------------------------------------------------- Pete Gontier | InterNet: 6600pete@ucsbuxa.ucsb.edu, BitNet: 6600pete@ucsbuxa Editor, Macker | Online Macintosh Programming Journal; mail for subscription Hire this kid | Mac, DOS, C, Pascal, asm, excellent communication skills
earleh@eleazar.dartmouth.edu (Earle R. Horton) (12/19/89)
In article <1989Dec19.001739.17771@oracle.com> omullarn@oracle.com (Oliver Mullarney) writes: ... >HLock and HUnlock are probably the best solution in this case, or the >HGetState and HSetState calls. One thing to remember when using HGetState and HSetState is that these are not available on early (64k ROM) machines, so you have to test for machine type or trap availability before using them. For an application program which probably owns all the Handles it deals with, HLock and HUnlock are appropriate nearly all the time. For code resources which manipulate data owned by applications or the system, H[GS]etState is a more application- friendly technique, if available. Earle R. Horton ZZ :wq .STOP ^C^C^C ^Z^Z^Z exit/save (emacs-save-files-and-die nil t)
tim@hoptoad.uucp (Tim Maroney) (12/19/89)
In article <9313@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >>Rect r; >>r = (*theControl)->contrlRect; >>RectRgn(myRgn, &r); In article <1989Dec19.001739.17771@oracle.com> omullarn@oracle.com (Oliver Mullarney) writes: >as a way of avoiding using HLock and HUnlock. Not in this case. What you >are handing to RectRgn is a pointer into a relocatable block. It may look >like a legitimate pointer, but it is not, so this *can* crap out. Wrong. Look at the code again. It's a pointer to a rectangle on the stack, which is in no way relocatable. Copying the rectangle out of the relocatable block onto the stack prevents the passing of a pointer into a relocatable block. You seem to have read this as "Rect *r; r = &(*theControl)->contrlRect; RectRgn(myRgn, r);" which would indeed be unsafe -- but that's not what I typed. >HLock and HUnlock are probably the best solution in this case, or the >HGetState and HSetState calls. Nope, there's more overhead involved in the trap calls than in the copying of eight bytes. And there's also less "cognitive overhead" if you avoid locking handles, since you never have to keep track of when things are supposed to be locked. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com FROM THE FOOL FILE: "The negro slaves of the South are the happiest, and, in some sense, the freest people in the world. The children and the aged and infirm work not at all, and yet have all the comforts and neccessaries of life provided for them." -- George Fitzhugh, CANNIBALS ALL! OR, SLAVES WITHOUT MASTERS, 1857
lippin@skippy.berkeley.edu (The Apathist) (12/19/89)
Recently 6600pete@hub.UUCP wrote: >DTS' official position now is that there are so many patched traps running >around calling the Memory Manager that you need to lock and unlock handles >around ANY trap call. The list, in other words, is no longer valid. For >the record, the following situations involve locked handles: > > passing elements of records pointed to by dereferenced handles as Pascal > "var" parameters > assigning return values from function-style traps to elements of records > pointed to by dereferenced handles > inside Pascal "with" statements which include handles in the "with" > >Can anyone think of any other situations? How about: In any piece of code that may be interrupted by some task that makes a toolbox call. Which, of course, is anything that runs without masking out interrupts. Seriously, if this were DTS's position, they would be saying that it's never legal to look into an unlocked handle. Coding around this would impose ridiculous penalties on performance. Luckily, they don't have to go this far, because we can be sure that interrupt routines don't move or purge handles. Why? Because they don't use traps that are on the danger list. On the other hand, they do want to say that nothing is forever -- once upon a time, SysBeep was a memory-safe trap. When all else fails, they just have to rely on your toolbox karma. --Tom Lippincott lippin@math.berkeley.edu "Just a moment... Just a moment... I'm picking up a fault in the AE-35 subunit. It will go one hundred percent failure within seventy-two hours." --HAL
jwright@cs.iastate.edu (Jim Wright) (12/20/89)
tim@hoptoad.UUCP (Tim Maroney) writes: | One final point: heap scramble mode in a debugger, while very slow, is | excellent at discovering when you have not respected handle | dereferencing issues. It is a good idea to do as complete a test run | as you can stand under heap scramble every few weeks or even days. I just checked this, but I'm seeking confirmation. Think Pascal does NOT have a heap scramble mode. T/F? What is the best way to get this heap scramble? -- Jim Wright jwright@atanasoff.cs.iastate.edu
6600pete@hub.UUCP (12/20/89)
From article <1989Dec19.091303.13316@agate.berkeley.edu>, by lippin@skippy.berkeley.edu (The Apathist): >>DTS' official position now is that there are so many patched traps running >>around calling the Memory Manager that you need to lock and unlock handles >>around ANY trap call. > Seriously, if this were DTS's position... I've seen it twice now posted by DTS employees with no disclaimers attached. With explicit declarations that it was official dogma, no less. (No, I don't log these things to disk.) I know it sounds ugly, but that's what's been said. Perhaps it IS the case that one should never write into an unlocked hanlde by any means. (Note: I said PERHAPS.) Additional input from DTS would be helpful, I'm sure. ------------------------------------------------------------------------------- Pete Gontier | InterNet: 6600pete@ucsbuxa.ucsb.edu, BitNet: 6600pete@ucsbuxa Editor, Macker | Online Macintosh Programming Journal; mail for subscription Hire this kid | Mac, DOS, C, Pascal, asm, excellent communication skills
shebanow@Apple.COM (Andrew Shebanow) (12/20/89)
In article <3373@hub.UUCP> 6600pete@hub.UUCP writes: >From article <1989Dec19.091303.13316@agate.berkeley.edu>, by lippin@skippy.berkeley.edu (The Apathist): >>>DTS' official position now is that there are so many patched traps running >>>around calling the Memory Manager that you need to lock and unlock handles >>>around ANY trap call. >Additional input from DTS would be helpful, I'm sure. >------------------------------------------------------------------------------- >Pete Gontier | InterNet: 6600pete@ucsbuxa.ucsb.edu, BitNet: 6600pete@ucsbuxa >Editor, Macker | Online Macintosh Programming Journal; mail for subscription >Hire this kid | Mac, DOS, C, Pascal, asm, excellent communication skills Your wish is my command... Anyhow, this statement of DTS's position is a bit of an oversimplification. It is true that the lists of traps that may move or purge memory are out of date, and that traps which currently are considered "safe" may become "unsafe" sometime in the future. Our recommendation is that developers err on the side of caution: if you are passing a dereferenced field of a handle by address, either use a temporary or lock the handle. I do feel that there are some calls which are "safe" to use dereferenced handles with, like BlockMove, some string manipulation calls, etc. Use your better judgment (or "Toolbox Karma", if you will). Tim Maroney is absolutely correct about the efficiency of temp variables vs HLock/HGetState calls: temps are much, much faster. Also, people who are doing code like this: HLock(h); p = *h; p->x = 1; p->y = 2; HUnlock(h); are wasting cycles. The HLock/Unlock here is totally unnecessary, since the compiler isn't going to generate code which will move or purge memory. For more information about unsafe references, I would encourage everyone to read Scott Knasters most excellent book, "How to Write Macintosh Software." Have fun, Andrew Shebanow MacDTS
chewy@apple.com (Paul Snively) (12/21/89)
In article <3373@hub.UUCP> 6600pete@hub.UUCP writes: > From article <1989Dec19.091303.13316@agate.berkeley.edu>, by lippin@skippy.berkeley.edu (The Apathist): > >>DTS' official position now is that there are so many patched traps running > >>around calling the Memory Manager that you need to lock and unlock handles > >>around ANY trap call. > > > Seriously, if this were DTS's position... > > I've seen it twice now posted by DTS employees with no disclaimers > attached. With explicit declarations that it was official dogma, > no less. (No, I don't log these things to disk.) > > I know it sounds ugly, but that's what's been said. > > Perhaps it IS the case that one should never write into an unlocked > hanlde by any means. (Note: I said PERHAPS.) > > Additional input from DTS would be helpful, I'm sure. Then again, maybe not... To the best of my knowledge, DTS hasn't formed an official position with locking and unlocking handles other than that you definitely need to do it if the trap(s) involved might shuffle memory around. We DO tend to tell people that with all the evil patches running around out there that you can't possibly know a priori whether a trap might move memory or not, so just code defensively. Assume the worst. That sort of thing. It's more a "you might wanna consider this" than a "don't do it." As has been pointed out in earlier posts, using a debugger with a heap scramble option can be very helpful. Generally speaking, a heap scramble function will ALWAYS shuffle the heap anytime that the heap COULD BE shuffled. The definition of this phrase is implementation-dependent; in TMON's case, it means whenever the handful of traps that could move memory are called either directly or indirectly. Another good thing to do is to have some utility (a debugger or an INIT) that stuffs address zero with some magical longword that's guaranteed to cause a Bus Error if accessed on any machine. It's useful for tracking down those intermitent NIL-handle/pointer references. __________________________________________________________________________ Just because I work for Apple Computer, Inc. doesn't mean that they believe what I believe or vice-versa. __________________________________________________________________________ C++ -- The language in which only friends can access your private members. __________________________________________________________________________
alain@atr-la.atr.co.jp (Alain de Cheveigne) (12/21/89)
in article <5896@internal.Apple.COM>$@$G(Jchewy@apple.com (Paul Snively) says: >Another good thing to do is to have some utility (a debugger or an INIT) >that stuffs address zero with some magical longword that's guaranteed to >cause a Bus Error if accessed on any machine. It's useful for tracking >down those intermitent NIL-handle/pointer references. My own Christmas wish is a program that you could run under MF with the program you're debugging, and that would allocate all the remaining memory and check it for over-writing. The idea that a bug from my program might be walking all over another program's memory space (or vice-versa) is unnerving. Alain de Cheveigne, alain@atr-la.atr.co.jp