Author Topic: UBOUND Causes "out of range" Error???  (Read 3015 times)

0 Members and 1 Guest are viewing this topic.

Offline SirCrow

  • Forum Regular
  • Posts: 144
    • View Profile
UBOUND Causes "out of range" Error???
« on: November 24, 2019, 03:20:04 pm »
I can't begin to imagine why the UBOUND line causes a Subscript out of range error:

Code: QB64: [Select]
  1. IF UBOUND(Seat) > 0 THEN 'In case Seat() has been ERASE'd
  2.     IF Seat(O) > 0 THEN
  3.  
  4.         Gr_Ship_Dist = SQR(((Ship_X - Grav_X) ^ 2) + ((Ship_Y - Grav_Y) ^ 2))
  5.         IF Gr_Ship_Dist > (Energy + 20) * 3 GOTO Next_Obj
  6.  
  7.     END IF

True, sometimes the code is executed after the array Seat has been ERASEd, and sometimes when it hasn't, but that's exactly why I added the UBOUND check.  And now that's causing an error!  Help me, please!
(BTW, I use OPTION BASE 1 in this prog.)
« Last Edit: November 24, 2019, 04:05:00 pm by SirCrow »
I may not always finish what I've started....

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: UBOUND Causes "out of range" Error???
« Reply #1 on: November 24, 2019, 04:15:21 pm »
So, if sometimes array exists and sometimes not, maybe try this method for array size test:

DIM c(5) AS LONG 'long = 4 bytes, records from 0 to 5 (6 records), so LEN = 24
PRINT LEN(c())

Or - if your code is used in SUB but array Seat is not SHARED, this can also do this error.

Edit:
If you use LEN on a field that does not exist, it will not return a value of 0, as you might expect, but a field value of 11 records. For example, if you write PRINT LEN (NotExists ()), you get a result of 44. The reason is that all variables in QB64 automatically get the assigned size of 10 (including 0)  therefore 11 records. Well, if the "NotExists" field does not exist, QB64 counts with the default SINGLE type, which is 4 bytes per record * 11 = 44.

So instead of a complicated field existence test, would always leave it defined, allow a record of 0, and insert a value of 1 if I wanted to process the field, or a value of 0 if I didn't want to process the field. Or you can use an auxiliary variable, but again, that's pretty confusing when more are needed and it's an easy way how to go crazy...  look to me... :)
« Last Edit: November 24, 2019, 04:40:18 pm by Petr »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: UBOUND Causes "out of range" Error???
« Reply #2 on: November 24, 2019, 05:56:53 pm »
Hi
please say me, is an O ora a 0 as index of array in this line of your code?
Code: QB64: [Select]
  1.   IF Seat(O) > 0 THEN

moreover as you can read here in the wiki  http://www.qb64.org/wiki/ERASE
Quote
Dynamic arrays must be REDIMensioned if they are referenced after erased.
Dimension subprocedure arrays as STATIC to use ERASE and not have to REDIM.

so if Seat is a dynamic array before use Ubound you must REDIM it.
Programming isn't difficult, only it's  consuming time and coffee

Offline SirCrow

  • Forum Regular
  • Posts: 144
    • View Profile
Re: UBOUND Causes "out of range" Error???
« Reply #3 on: November 26, 2019, 07:25:45 pm »
Hi
please say me, is an O ora a 0 as index of array in this line of your code?
Code: QB64: [Select]
  1.   IF Seat(O) > 0 THEN

moreover as you can read here in the wiki  http://www.qb64.org/wiki/ERASE
so if Seat is a dynamic array before use Ubound you must REDIM it.

It's the letter O, as in Object.  Variable O is SHARED, as I recall.  Thanks.
I may not always finish what I've started....

Offline SirCrow

  • Forum Regular
  • Posts: 144
    • View Profile
Re: UBOUND Causes "out of range" Error???
« Reply #4 on: November 26, 2019, 07:40:48 pm »
So, if sometimes array exists and sometimes not, maybe try this method for array size test:

DIM c(5) AS LONG 'long = 4 bytes, records from 0 to 5 (6 records), so LEN = 24
PRINT LEN(c())

Or - if your code is used in SUB but array Seat is not SHARED, this can also do this error.

Edit:
If you use LEN on a field that does not exist, it will not return a value of 0, as you might expect, but a field value of 11 records. For example, if you write PRINT LEN (NotExists ()), you get a result of 44. The reason is that all variables in QB64 automatically get the assigned size of 10 (including 0)  therefore 11 records. Well, if the "NotExists" field does not exist, QB64 counts with the default SINGLE type, which is 4 bytes per record * 11 = 44.

So instead of a complicated field existence test, would always leave it defined, allow a record of 0, and insert a value of 1 if I wanted to process the field, or a value of 0 if I didn't want to process the field. Or you can use an auxiliary variable, but again, that's pretty confusing when more are needed and it's an easy way how to go crazy...  look to me... :)

I think I had Seat SHARED at one time, encountered errors that confused me, and ended up changing it.  Much still confuses me, despite all the experience.  Anything I don't do often tends to drift to the back of my mind, if not entirely out of my head.

Indeed, I try to avoid adding more variables whenever possible.  In fact, I think it's due to my desire to reuse as much code as possible that my programs always seem to end up all twisty and complicated.  I believe it was once called spaghetti code.  Thanks for the input.
I may not always finish what I've started....