Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!hao!oddjob!gargoyle!ihnp4!cuae2!killer!usl!prm From: prm@usl (Patrick Royce Michaud) Newsgroups: comp.sys.amiga Subject: Re: Just another BASIC bug Message-ID: <153@usl> Date: Mon, 17-Aug-87 18:32:56 EDT Article-I.D.: usl.153 Posted: Mon Aug 17 18:32:56 1987 Date-Received: Thu, 20-Aug-87 06:30:49 EDT References: <3645@ecsvax.UUCP> Reply-To: ut-sally!usl!prm (Patrick Royce Michaud) Organization: CACS, Univ of SW La, Lafayette, LA Lines: 85 Summary: Watch out for memory reallocs In article <3645@ecsvax.UUCP> urjlew@ecsvax.UUCP (Rostyk Lewyckyj) writes: > >Several weeks ago I posted the following note describing a suspected >Amiga BASIC problem. Since I did not receive a salvo of fire from >the guns of Commodore, I take this as a tacit admision of another >bug in this version of BASIC. Actually, the people at Commodore may not be the ones to ask about it, as AmigaBasic is made by Microsoft :-). At any rate, the bug is not in AmigaBasic, but in your code (see below): >------------ original article follows ---------------------- >Included below is an Amiga BASIC program whose purpose is supposed to be >to read in a packed record of 8204 integers stored as one record of a >random file, and unpack the record into an array. Why I am trying to do >this is irrelevant just now. What is relevant is that this program keeps >getting visited by the GURU and I don't know why. > >CLEAR , 1030,1030 >CLEAR , 40000&,2048 >OPEN "R",1, "matfile", 16410 >FIELD 1,16408 AS a$ >LSET a$="abcd" >DIM ps%(8203) >ps%(0)=0 >b&=VARPTR(ps%(0)) >c&=b& >GET #1,1 >a&=SADD(a$) >FOR i&=a& TO a&+16407 STEP 2 >POKEW c&,PEEKW(i&) >c&=c&+2 >NEXT i& >END > >I would much appreciate an explanation of why its happening. Ok, here's my explanation. The problem statement is the "c&=b&". (really!) Your second CLEAR statement allocates 40000 bytes of space for AmigaBASIC's data segment. This is where all of your variables (simple variables, arrays, etc.) are going to be stored. It turns out that the variables aren't stored helter-skelter as they are declared, but that they do have some semblence of order placed upon them. You can think of the data segment as a table, which grows as new variables are declared within the program. The organization of this table is such that simple variables come first, followed by the array variables. What is happening with your program is this -- you first DIM the ps%() array, so AmigaBASIC goes and allocates space (16408+overhead bytes) for it. Later, your program says "b&=VARPTR(ps%(0))". Since simple variables have to come _before_ array variables in the data segment, AmigaBASIC moves the ps%() array in the data segment to make enough room for b&. It then gets the address of ps%() and puts it in b& -- still no problem. But what is a problem is your next statement-- "c&=b&". Since c& has not been previously declared, AmigaBASIC has to find space for it. Again, following the "simple variable before array" rule, it moves the array AGAIN to make enough room for c&. But, c& is getting the OLD address of the array, and not the new one. Thus, when you finally get down to POKEWing into what c& thinks is the start of the array, you're mucking around in territory that isn't yours, and trashing up the AmigaBASIC data segment. The solution to this problem is easy -- make sure that no other "new" variable declarations occur between the time the VARPTR is done and the actual POKEW takes place. If any new variable declarations do occur, then the VARPTR of the array is gonna change (in this case, c&, a&, and i& all cause the VARPTR of ps%() to change). One solution is to do "c&=0:a&=0:i&=0" before you do the "b&=VARPTR(ps%(0))" statement. Thus, these variables will have already been declared by the time the VARPTR takes place, and it won't move by the time you do the POKEWs. A better solution might be to use one of the following (and avoid VARPTR altogther): a&=SADD(a$) | a&=SADD(a$) FOR i = 0 to 8203 | FOR i = 0 to 8203 ps%(i) = PEEKW(a&+i*2) | ps%(i) = cvi(mid$(a$,i*2,2)) NEXT i | NEXT i These present somewhat cleaner alternatives to PEEKW and POKEW, although I can certainly find reasons why you might want to use PEEKW and POKEW instead of the above examples. At any rate, I hope this helps to solve your problem. Patrick R. Michaud USL NASA Project Member "my opinions are my own" ut-sally!usl!prm