Page 1 of 1

A bug in QB? Or is this a feature?

Posted: Thu Jun 04, 2020 6:34 am
by RETROQB45
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 :shock:)

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? :lol:

Re: A bug in QB? Or is this a feature?

Posted: Sun Jun 21, 2020 4:49 pm
by Erik
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.

Re: A bug in QB? Or is this a feature?

Posted: Thu Aug 06, 2020 9:52 pm
by nikomaru
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!

Re: A bug in QB? Or is this a feature?

Posted: Sat Nov 21, 2020 3:43 pm
by angros47
Wow! It's the first time in about 10 years that I see something new about QB, on this forum.

Re: A bug in QB? Or is this a feature?

Posted: Mon Dec 07, 2020 9:24 am
by angros47
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 :shock:)

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.