Path: utzoo!attcan!uunet!tut.cis.ohio-state.edu!gibson From: gibson@tut.cis.ohio-state.edu (William Kerr Gibson) Newsgroups: comp.sys.mac.hypercard Subject: Re: Is PasToZero necessary? Keywords: PasToZero not real problem Message-ID: <81983@tut.cis.ohio-state.edu> Date: 9 Jul 90 15:03:54 GMT References: <12477@june.cs.washington.edu> Reply-To: William Kerr Gibson Organization: Ohio State University Computer and Information Science Lines: 125 In article <12477@june.cs.washington.edu> moore@cs.washington.edu (Charles Moore) writes: >Is a call to PasToZero necessary in order to return a result to Hypercard >from an XCMD? The appendix to the HyperCard Script Language Guide is ... >is the space for this string allocated? I allocated space within my >XCMD with the declaration: > >char resultStr[80]; > >and then tried to return this value with the assignment: > >paramPtr->returnValue = (Handle)&resultStr; > >The result was a system error. Does this mean that PasToZero, in ... > >Charles Moore Howdy, my name is seann i am Kerr's brother. You have a couple of problems here: 1st, I assume that you have declared resultStr in your main as one of the local variables. This means that the 80 bytes of space that you have declared are on the Stack; thus when you return to hypercard, you have NO GAURANTEE at all with what hypercard will do to the stack, and since hypercard does not know that this result parameter is on the stack, it could easily overwrite this area. As a general RULE, NEVER return a pointer to anything that you have declared as local storage in a 'c' function. Your second problem, and perhaps a worse one is that you HAVE NOT returned a handle at all! what you have returned is merely a pointer. In fact, you have not really even returned a pointer to a pointer, which is as i believe, what you are trying to return. Because, since resultStr is on the stack (the space is on the stack) refering to resultStr without any brackets [] is the same as refering to &resultStr. in other words: char resultStr[80]; char *a; a = resultStr; is the same as... a = &resultStr; but at any rate even if you do return a pointer to a pointer this will NOT help you at all because a pointer to a pointer is NOT the same as a handle. A handle will be explicitly declared as such in hypercards heap zone so that it knows the size and can move it around and compact the heap and do whatever it likes. In other words, paramPtr-> returnValue is a space of 4 bytes and you have put 4 bytes in there that happen to be a pointer to a group of 80 bytes. now when hypercard tries to dispose of this handle or set the size different, or do any memory operations with it, the results are unpredictable, and could easily destroy hypercards heap which will eventually cause any number of system errors to occur. and now my brother (the hypercard XCMD whizz boy) will tell you what you should really do... sorry Charlie, but you are going to have to declare a handle somewhere. Fortunately this is not too difficult. When you use paramPtr->returnValue you have two options. 1. you can assign paramPtr->returnValue to an existing handle (much like you have tried to do in your code). In this case you need to have actually declared space for your handle with NewHandle(). Once you have assigned returnValue you must NOT dispose of the old handle as HyperCard will dispose of it for you. E.g. { Handle resultStr; resultStr = NewHandle((long) 80); /* declare space for the handle */ ... strcpy(*resultStr,"This is my return message"); /* perform string operations */ ... paramPtr->returnValue = resultStr; /* returnValue is now same as resultStr */ /* WARNING! Do not dispose of resultStr. Hypercard will dispose of */ /* paramPtr->returnValue on its own, which amounts to the same thing */ return(); } 2. The other thing you can do is to declare space for returnValue at the time you assign your string to it. { char resultStr[80]; ... paramPtr->returnValue = CopyStrToHand(resultStr); return(); } /* CopyStrToHand function is below */ /* This is taken from "XCMD's For HyperCard" by Gary Bond */ Handle CopyStrToHand(str) char *str; { Handle newHndl; newHndl = (Handle) NewHandle((long) strlen(str) + 1); strcpy((char *) (*newHndl), str); return(newHndl); } That's it.... Hope this helps you out! Kerr Gibson CIS Dept OSU. (614)292-0915 __---------------------__ gibson@tut.cis.ohio-state.edu _____________ / >------------------- att-cb!osu-cis!tut.cis.oh...!gibson `-~~~~~~~~~"--'---/ / OSU 2036 neil av. Col. Oh. 43210-1277 `---`==________/ Engage!