[Gambas-user] Minor bug with READ & WRITE commands?

Benoit Minisini gambas at ...1...
Mon Jan 19 02:01:51 CET 2009


On vendredi 16 janvier 2009, nando wrote:
> Benoit,
>
> Question regarding the line:
> > > WRITE #pResult + (ii * 8), .x
>
> does WRITE see it casted as variant or int ?
> -Fernando
>

You exactly got the point. :-)

As fResult is an Object[] array, fResult[ii].x is a Variant.

Why? Because, in Gambas, the datatype of an operator or a function is never 
more precise than the datatype of the arguments, unless the operator or 
function always returns the same datatype. Read that sentence at least twice.

So, as fResult is Object[], then fResult[ii] is Object, and fResult[ii].x is 
always a Variant, as the interpreter cannot know that fResult[ii] is always a 
Class1.

As READ and WRITE receive a Variant, they read/write a byte before the value 
in memory. 

So what is written at the pointer is not two bytes &H64+&H00 (the 100 value) 
but three bytes &H04+&H64+&H00 (&H04 meaning Integer).

As the memory address is computed at each loop, the third byte is replaced by 
the first byte of the next write. The last written byte is outside of the 
array. It does not crash because memory allocation are often rounded by the C 
library.

When reading, what happens? The GetAStruct C function receives:

&H04+&H64+ &H04+&HC8+ &H04+&H64 +...+ &H04+&HC8+&H00

And modifies it:

&H0E+&H64+ &H05+&HC8+ ...

Then READ wants to read a Variant, and so interprets the first byte, &H0E, as 
a datatype that means...a Class, something that is cannot understand, and so 
you get an error message. But in other situations, you can crash the 
interpreter, because READ can write in memory more than expected!

What is the solution? You have to tell Gambas which is the real datatype to 
read and write.

The first solutiion is what you did: using a local variable with the accurate 
datatype.

The second solution is not having Object as intermediate expression datatype. 
Instead of:

  WITH fResult[ii]

Do that:

  DIM hClass AS Class1

  hClass = fResult[ii]
  WITH hClass

Then the interpreter will know at runtime that hClass is a Class1, and so that 
hClass.x is always an integer.

So, all that is not really a bug, but I admit it is a bit weird, and not 
beginner-friendly.

In Gambas 3, I'm currently thinking about a better, or at least clearer 
syntax. It will be a mix of:

- True memory streams, i.e. a class that inherits Stream and that points at a 
memory emplacement.

- Classic Basic memory access function. PEEK, POKE ? :-) And/Or MkInt$(), 
MkLong$()...

- Explicitely specifying the datatype in READ and/or WRITE, or having 
ReadInteger(), ReadFloat(), WriteInteger()... methods in the Stream class, or 
as subroutines.

People, tell me what you think about that. I'm going to bed now.

-- 
Benoit Minisini




More information about the User mailing list