PDA

View Full Version : Run-time error in TAB version 12



ErosOlmi
16-09-2006, 20:47
Catventure,

I was testing all script in order to find possible incompatible code due to latest introduction of array bound checking.
I've found a problem in TAB Player. Details are the following:

Line: 2394
Error: Dimension 1 should be between 1 and 100. Current value: 0

IF (CHECKCOND="charsexn2=it") AND (CHARN2>0 AND CHARSEX(CHARN1)<>2) THEN
It seems CHARN1 is equal to zero.

I think there are other problems of the same type in TAB.
If you prefer you can quickly fix it using "#DEFAULT BOUNDCHECK OFF" directive at the beginning of the script but I suggest to see why this is happening. Out of bound errors can create impredictable results very difficult to find the cause.

Ciao
Eros

Petr Schreiber
16-09-2006, 20:56
Hi,

I must confirm this problem too.
It happens also in the editor, when I try to "Test game".


Petr

catventure
16-09-2006, 21:16
Hi,

Seems the new preview may be cleverly picking up on a coding error I have made:

Code

IF (CHECKCOND="charsexn2=it") AND (CHARN2>0 AND CHARSEX(CHARN1)<>2) THEN

Should be:

IF (CHECKCOND="charsexn2=it") AND (CHARN2>0 AND CHARSEX(CHARN2)<>2) THEN


I am getting new preview to check if so and anything else - then will post an update to the TAB page.

Thanks,
catventure

catventure
16-09-2006, 22:22
Hi,

I have new preview but even after fixing my coding mistake the RunTime error still occurs:

IF (CHECKCOND="charsexn2=it") AND (CHARN2>0) AND (CHARSEX(CHARN2)<>2) THEN

This did not happen in previous preview...
I had assumed that code like this was OK.

I found I can stop the error by doing this:

If instr(checkcond,"charsexn2=it")=1 then
if charn2>0 and charsex(charn2)<>2 then
............
............
end if
end if

However I have now come across other instances where the 'boundcheck' causes runtime errors - they are all similar to above. The code *looks perfectly OK* to me but the boundcheck does not seem to like multiple 'AND' in the IF... Then...

As Eros has pointed out I can use


#default boundcheck off


at the head of the program listing and TAB runs just fine..

catventure

ErosOlmi
16-09-2006, 23:03
catventure,

I think I've understand the situation. The problem is the IF test that is completelly evaluated even if "charn2>0". And this is correct.
If you want that "charsex(charn2)<>2" is evaluated only if "charn2>0" you have to break into 2 tests because "charn2>0 and charsex(charn2)" is condidered a single numeric expression and evaluated as a whoole.

This behaviour is the same in other languages I suppose.

Correct test should be:

if charn2>0 then
if charsex(charn2)<>2 then
...
...
end if
end if
In this case second test is performed only if first test is TRUE.

Ciao
Eros

catventure
17-09-2006, 09:45
Hello,

An example IF/THEN statement containing AND and OR such as the following will not produce any runtime error by default boundcheck:


dim b as long
dim c as string

b=34
c="some string"

if (b>0 or b<2) and b<>65 AND b<=34 AND c="some string" _
AND b=34 And c<>"another string" and instr(c,"me")=3 then

msgbox (0,"I am showing because the IF conditions are true")

else

msgbox (0,"I am shown when the IF conditions are false!")

end if

I am hoping that my line syntax construction of the IF/THEN statements in TAB will continue to be legal and acceptable to thinBasic generally or I would need to effect some extensive rewriting of code...
#DEFAULT BOUNDCHECK OFF and everything is OK.

Regards,
catventure.

ErosOlmi
17-09-2006, 10:57
catventure,

your IF example is ok. Even more complex with many level of parenthesis is OK.
It is not a matter of how complex it is, but the fact that it is considered a single numeric expression that is evaluated in one go.

If inside the test there is something not correct (like referencing an array index out of bound), parsing has to stop.

There are some reasons why we introduced bound checking but most important is the fact to help to find possible errors. Previous version, in case of index outside bounds, was just ignoring the error and returning zero for numeric arrays and an empty string for string arrays. In many cases this is not correct because, maybe, the zero or empty values are valid for your script and can produce side effects very difficult to find.

Eros

catventure
17-09-2006, 11:08
Ok Eros, think I understand it a bit better now - but not entirely!

Array boundcheck is something new to me...

I'll check further but for now have posted a revised TAB Alpha 12 to the project site including the "#Default Boundcheck off" to bypass the RunTime Errors.

Do you have a very simple example code snippet that will produce the error so it becomes much clearer and more understandable to me?
Sorry for prolonging this thread but is a little worrying to me :(

Best wishes,
catventure

ErosOlmi
17-09-2006, 11:41
No problem.

Arrays or variables are nothing more than a sequence of bytes in memory.
Every different single variable type allocate a different number of bytes:

Table 1:[/b] single variable example"]
Variable example Bytes allocated Representation
DIM MyLong AS LONG allocates 4 bytes ####
DIM MyQuad AS QUAD allocates 8 bytes ########
DIM MyExt AS EXT allocates 10 bytes ##########


Arrays are exactly the same like a standard variable but instead of allocating a number of bytes needed only for one variable (in this case it is called item) it allocates a multiple of tha base variable size, all in a single block of memory. So, for example:
Table 2:[/b] array variable example"]
Array example Bytes allocated Representation
DIM MyLong(2) AS LONG allocates 4 * 2 bytes #### ####
DIM MyQuad(2) AS QUAD allocates 8 * 2 bytes ######## ########
DIM MyExt(2) AS EXT allocates 10 * 2 bytes ########## ##########


When, for example, you write something like MyLong(2) = 123, the interpreter (or any other languages) is transformig the number 123 into its binary LONG form of 4 bytes, pointing at byte 5 of the 8 allocated buffer and writing 4 bytes (it is element 2 of the array).

But when you write something MyLong(3) = 123 what can happen? Let's see again the process: interpreter transform 123 into a LONG of 4 bytes, calculate the position of element 3 that is 9 (SizeOF(LONG) * (element - 1) + 1 = 4 * (3 - 1) + 1 = 9) and try to write 4 bytes at byte 9 of 8 allocated.
2 main events can occur:

at byte 9 there was another memory block allocated by thinBasic process. In this case no GPF but thinBasic can have unpredictable behave due to the nature of the memory block altered (can be another variable, can be an internal structure, or whaever)
at byte 9 nothing was allocated, in this case a GPF should occur because you are using a memory space non previously allocated


The same happen for all other variables/arrays types.
More complex is for dynamic STRINGs because dynamic strings are in reality a pointer pointing to a dynamic memory area that is allocated/deallocated/reallocated every time you change the string.

Consider the fact that from WIN9X to WIN2K all has changed into operating system memory allocation. The most important aspect is that under WIN9X memory is shared by all process running so writing outside permitted allocated memory can even hang the system (you can write in the memory of another process). While under WIN2K or upper OSs memory is allocated per process so writing outside the allocated memory of your process in intercepted by the OS and process, if needed, is terminated (GPF) without effecting all other process running.

Hope to have given some more details to help understand why we have decided to check elements bound in arrays.

Ciao
Eros

catventure
17-09-2006, 13:33
A very elegant explanation Eros! :o

I begin to see the value in having this kind of check for pinpointing discrepancies when debugging and why you have thought of including this.

So my code is not necessarily wrong then or....?



IF (CHECKCOND="charsexn2=it") AND (CHARN2>0) AND (CHARSEX(CHARN2)<>2) THEN


If variable 'charn2' is equal to 0 (which it would be initially in my prog) the boundcheck will notify an error?

catventure

ErosOlmi
17-09-2006, 14:29
Yes, exactly.

Your code is not logically wrong but you would get GPF in many languages because usually the IF consition is considered ONE SINGLE statement to be executed asa whoole. Impossible (well very difficult) to detect and optimize an IF statement. In your case because the 2 tests are using AND, one can think that because fist fail than all the subsequent would fail because of AND. But what in a more complex IF condition with many AND, OR, NOT all with different precedence because of multiple parenthesis level?

Ciao
Eros