If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!
Moderators: Pete, Mods
-
RETROQB45
- Newbie
- Posts: 4
- Joined: Wed Jun 03, 2020 2:57 pm
Post
by RETROQB45 » Thu Jun 04, 2020 6:34 am
Here's an interesting bug I've found messing with my old QuickBASIC programs.
I suspect that anyone has spotted it before, but Google doesn't seem to know anything about this
Please read carefully the following code and guess what it will print:
Code: Select all
DIM SHARED a(2)
a(1) = 10
PRINT "before the call:"; a(1)
f a(1)
PRINT "after the call:"; a(1)
SUB f (v)
PRINT "in the sub before modifying:"; a(1)
v = 2
PRINT "in the sub after modifying:"; a(1)
END SUB
Then run it in any
ORIGINAL DOS QuickBASIC (QBasic/QB4.5/PDS/VBDOS) and be shocked with its "correct" answer (10 10 10 2

)
The key point here is passing an array element by reference.
Btw this code works as expected in QB64.
And now I wonder how can it be that I've never suffered from this (didn't even know of) in my childhood?

-
Erik
- Veteran
- Posts: 56
- Joined: Wed Jun 20, 2007 12:31 pm
- Location: LI, NY
-
Contact:
Post
by Erik » Sun Jun 21, 2020 4:49 pm
Interesting! So it basically treats the "v" parameter as a local variable in the SUB and doesn't actually update the value of the array element passed until the code is returning from the SUB.
Passing in the whole array works as expected. The source array is updated when the parameter array gets updated.
Ex:
Code: Select all
DECLARE SUB SetVals (ArrayIn() AS INTEGER)
DIM SHARED test(1) AS INTEGER
test(0) = 500
test(1) = 900
CLS
PRINT "Before sub call"
PRINT "test(0) "; test(0)
PRINT "test(1) "; test(1)
PRINT "--------------------------------------"
CALL SetVals(test())
PRINT "After sub call"
PRINT "test(0) "; test(0)
PRINT "test(1) "; test(1)
PRINT "--------------------------------------"
SUB SetVals (ArrayIn() AS INTEGER)
PRINT "Start sub call"
PRINT "test(0) "; test(0)
PRINT "test(1) "; test(1)
PRINT "ArrayIn(0) "; ArrayIn(0)
PRINT "ArrayIn(1) "; ArrayIn(1)
PRINT "--------------------------------------"
ArrayIn(0) = 400
ArrayIn(1) = 200
PRINT "End sub call"
PRINT "test(0) "; test(0)
PRINT "test(1) "; test(1)
PRINT "ArrayIn(0) "; ArrayIn(0)
PRINT "ArrayIn(1) "; ArrayIn(1)
PRINT "--------------------------------------"
END SUB
Output:
Code: Select all
Before sub call
test(0) 500
test(1) 900
--------------------------------------
Start sub call
test(0) 500
test(1) 900
ArrayIn(0) 500
ArrayIn(1) 900
--------------------------------------
End sub call
test(0) 400
test(1) 200
ArrayIn(0) 400
ArrayIn(1) 200
--------------------------------------
After sub call
test(0) 400
test(1) 200
--------------------------------------
Nice find. I'm sure that's caused headaches to others in the past.
-
nikomaru
- Newbie
- Posts: 7
- Joined: Wed Nov 28, 2018 7:35 pm
Post
by nikomaru » Thu Aug 06, 2020 9:52 pm
Ha! I had this issue as well, creating a Frogger clone, and fixed it with passing BY instead of referencing. Just trying to save memory by not using a stupid amount of globals, sheesh!
-
angros47
- Veteran
- Posts: 78
- Joined: Mon Sep 08, 2008 12:52 pm
-
Contact:
Post
by angros47 » Sat Nov 21, 2020 3:43 pm
Wow! It's the first time in about 10 years that I see something new about QB, on this forum.
-
angros47
- Veteran
- Posts: 78
- Joined: Mon Sep 08, 2008 12:52 pm
-
Contact:
Post
by angros47 » Mon Dec 07, 2020 9:24 am
RETROQB45 wrote: ↑Thu Jun 04, 2020 6:34 am
Here's an interesting bug I've found messing with my old QuickBASIC programs.
.....
Then run it in any
ORIGINAL DOS QuickBASIC (QBasic/QB4.5/PDS/VBDOS) and be shocked with its "correct" answer (10 10 10 2

)
Interesting thing: I tried it in QB45, and indeed it happens like you described. Then I tried compiling it (with "make exe file"), and the compiled program returns 10 10 2 2). So, the interpreter is not consistent with the compiler.
Indeed, the "correct" behavior is the most logical one for a compiler (since it works by reference). Looks like the interpreter, on the other hand, works on a copy and tries to adjust the references in the end.