home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!wupost!waikato.ac.nz!comp.vuw.ac.nz!actrix!Bruce.Hoult
- Newsgroups: comp.sys.mac.programmer
- Subject: Re: Parameter Types for GetIndString, ParamText, NewString, et al.
- Message-ID: <1992Jul25.121251.6284@actrix.gen.nz>
- From: Bruce.Hoult@bbs.actrix.gen.nz
- Date: Sat, 25 Jul 1992 12:12:51 GMT
- Sender: Bruce.Hoult@actrix.gen.nz (Bruce Hoult)
- References: <1992Jul25.002622.1@tesla.njit.edu>
- Organization: Actrix Information Exchange
- Lines: 166
-
- In article <1992Jul25.002622.1@tesla.njit.edu> erh0362@tesla.njit.edu (Elliotte Rusty Harold) writes:
- >
- > Can anyone spot the problem in the following code?
-
- Well, uh, just one or two.. :-)
-
-
- > It typically crashes
- > at either the GetIndString, the ParamText, or the StopAlert call. I suspect
- > I'm not passing the proper type of argument to one of the toolbox calls (e.g.
- > sending a Str255 where I should be passing a StringPtr or vice versa) but I've
-
- No, you're corrupting the heap.
-
-
- > tried this with many different combinations of variable
- > type without success. The various
- > sample source I've looked at has been inconsistent on the type of argument
- > passed to these toolbox calls, i.e. some pass strings and some pass StringPtr's.
-
- Once you start mucking around behind the compiler's back by using *
- and & the declared types or variables matters not one bit -- it becomes
- *your* responsibility to know what you're doing.
-
- Read the documentation. Understand in particular where the Toolbox is
- going to return a value to you and make sure you're very sure about
- where it is going to write that information for you and that there is
- enough space for what it is going to write.
-
-
- > Do I need to allocate space for errorString (a Str255) or is it automatically
- > allocated since errorString is really an array of 256 chars? If I
- > do need to allocate space, how?
-
- No you don't, because it is a local variable. You need to learn what
- a C compiler does with local variables -- where they are allocated
- space (on the stack) and when (allocated at function entry,
- deallocated at function exit).
-
-
- > Can I dispense with the StringHandle
- > errorStringH entirely and just use errorString and &errorString as necessary?
- > All suggestions appreciated. Problem function follows.
-
- Yes. Just look at the definition of GetIndString:
-
- ---------
- PROCEDURE GetIndString(VAR theString: Str255;strListID: INTEGER;index: INTEGER);
- File {PInterfaces}ToolUtils.p
- Inside Macintosh reference: I-468
- Moves or purges memory.
- [Not in ROM]
-
- GetIndString returns in theString a string in the string list that has the resource
- ID strListID. It reads the string list from the resource file if necessary, by calling
- the Resource Manager function GetResource('STR#',strListID). It returns the string
- specified by the index parameter, which can range from 1 to the number of strings in
- the list. If the resource cant be read or the index is out of range, the empty
- string is returned.
- ---------
-
- This means that you have to somehow allocate enough space for a 255 character
- string, and then tell GetIndString where it is. It could be a local variable
- (like your "errorString" or on the heap (like your errorStringH), as long
- as it's big enough.
-
- Let's have a look at your code as it stands:
-
- > Boolean IOCheck(OSErr errornumber) {
- >
- > Str255 errorString;
- > StringHandle errorStringH;
- >
- > if (errornumber != noErr) {
- >
- > errorStringH = NewString(&errorString);
-
- Do you know what NewString does? Let's look in TFM, shall we?
-
- ----------
- FUNCTION NewString(theString: Str255): StringHandle;
- INLINE $A906;
- File {PInterfaces}ToolUtils.p
- Inside Macintosh reference: I-468
- Trap number: A906
- Moves or purges memory.
- NewString allocates the specified string as a relocatable object in the heap and
- returns a handle to it.
-
- Note: NewString returns a handle to a string whose size is based on its
- actual length (not necessarily 255); if you're going to use Pascal
- string functions that could change the length of the string, you may
- want to call SetString or the Memory Manager procedure SetHandleSize
- first to set the string to the maximum size.
- ----------
-
- Read that note carefully -- it's there to help stop you making a stupid
- mistake.
-
- NewString is taking what's in your string variable (errorString) and
- copying it into a *new* string in a handle. What's in errorString?
- You don't know -- you've never put anything in it so it could be
- totally random. The chances are though, that it's pretty short -- the
- chances are excellent that it's zero to ten characters long. That means
- that errorStringH points to something that it probably much smaller
- than is needed to hold a full Str255.
-
-
- > HLock(errorStringH);
- > GetIndString(**errorStringH, IO_ERROR_STRINGS,
- > -1 * errornumber - ZEROTH_IO_ERROR );
-
- BANG! You probably just corrupted the heap by writing past the end of
- the space pointed to by errorStringH.
-
- Either errorString or &errorString would have been fine here (either because
- C automatically takes the address of an array in a parameter context
- -- bletch). Either *errorStringH (which I'd prefer) or your
- **errorStringH would have been fine if you'd made sure there was
- enough space for the result -- something like "errorStringH =
- NewHandle(256)" would have been fine instead of the NewString.
-
-
- > if ( errorString == NIL_POINTER) {
-
- Huh??
-
- Three things wrong here:
-
- 1) errorString has nothing to do with errorStringH at this point.
- errorStringH points at a *copy* of errorString, not at the original.
- The GetIndString will change the copy but not the original.
-
- 2) GetIndString returns an empty string on error, not a null pointer.
- RTFM above -- and there's no way it *could* return a null pointer,
- since you're supplying the storage for it to alter, not the other way around.
-
- You should be testing **errorStringH == 0 or (*errorStringH)[0] == 0 or
- errorString[0] == 0 (if you weren't using the unnecesary errorStringH).
-
-
- 3) It's not possible for "errorString == NIL_POINTER" to ever be true,
- since errorString (really &errorString because of C's automatic conversion) is
- a local variable on the stack and thus can never have an address of zero.
-
-
- The rest of the code looks OK.
-
- You've got two options:
-
- 1) junk errorString, change the NewString to NewHandle and
- "errorString == NIL_POINTER" to "**errorStringH == 0".
-
- or
-
- 2) junk errorStringH and use errorString or &errorString (the & will
- always be reundant in C) and "errorString[0] == 0".
-
- -- Bruce
- (who didn't mean to be as abusive as he probably sounded)
-
- --
- Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 477 2116
- BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ
- "Cray's producing a 200 MIPS personal computer with 64MB RAM and a 1 GB
- hard disk that fits in your pocket!" "Great! Is it PC compatable?"
-