Topic : The GFA-Basic Compendium
Author : GFA Systemtechnik GmbH
Version : GFABasic.HYP v2.98 (12/31/2023)
Subject : Documentation/Programming
Nodes : 899
Index Size : 28056
HCP-Version : 3
Compiled on : Atari
@charset : atarist
@lang :
@default : Document not found
@help : Help
@options : +g -i -s +z
@width : 75
@hostname : STRNGSRV
@hostname : CAB
@hostname : HIGHWIRE
@hostname : THING
View Ref-FileThe local=FN bug GFA Basic FAQ (English)
Symptoms: The local variable never receives the FN value returned. The
system may hang at a later point in the program.
Description: This problem arises when a function assigns a value to local
variable and a DIM or ERASE occurs before the function
returns.
An example source is given below that explains how, and can
diagnose if your version of GFA has this problem:
PROCEDURE test
LOCAL a& ! any variable, any variable type
' a&=5
adr=V:a& ! note original address of a&
PRINT "defined",adr,"val"'a&
' a&=FN oh_oh ! new value assigned by way of
'^! function
'\-- error occurs here, in assignment!!!
'PRINT "after",V:a&,"val"'a& ! local variables have moved
PRINT "val at ",adr,WORD{adr} ! new value is at old address
RETURNFUNCTION oh_oh
DIM a$(10) ! address of local a&...
RETURN 10 ! in calling routine moved here
ENDFUNCSome remarks to this:* The fault occurs both in the interpreter and in the compiled
code.
* The fault occurs when assigning any local variable (numeric or
string) a value from a function inside of which, at any
sublevel, a DIM or ERASE statement is executed.
* The fault does not occur when existing string elements in an
array are reassigned. The error arises only when
(re)dimensioning string or numeric arrays.
* The fault does not affect local variables returned as a VAR parameter. Nor does it affect assignment to a global variable.
Analysis: This is a memory management bug caused by how the function
assigns a value to a variable. Any program which has functions
and uses dynamic management of arrays has the potential for
unexplained and seemingly random problems. Note that the
problem is especially treacherous since the cause can be
buried far below where the faulty assignment occurs, e.g. the
assigning function may call a procedure which calls a
procedure which calls a procedure which performs a DIM.Workaround: A workaround to function assignment of a local variable, is to
return the value using a VAR-defined parameter in the call
(i.e. using a procedure), or to have the function return to a
global variable. Or to not use dynamic arrays, or at least
carefully structure when and how they are changed.
Evidently the function assignment involves an internal V:a&
reference being generated before executing the function call. The
DIM command inside the function allocates global variable space
for the array (the element pointers in the case of string arrays,
the physical array in the case of numeric arrays), which pushes
all existing local variables addresses. (See detailed notes on
memory use, below.) This is a problem only because it occurs at
runtime when we have a static address reference pending in the
function. The return value is thus written to the old invalid
address, and variable a& itself, now at another address, is
unmodified.
Note that attempting to ERASE the array dimensioned in this
situation will cause the system to hang, since when the function
return assigned the value, the old address for a& then points
into a descriptor structure belonging to the new array. Where it
points when an existing array is erased or redimensioned is less
obvious, as is what happens then.
Furthermore, any local variable which is assigned ABSOLUTE will
in a case like this (incorrectly) behave as a global and not have
its address moved, see below:
LOCAL a&,b&
...
b&=ABSOLUTE V:a&
b&=FN oh_oh
...
... Variable b& is not moved and so gets the new value.
Note that the address of b& is actually now invalid, and points
into space reserved for the array.
(V:a&=V:b& is no longer true!)
This behaviour is quite unlike e.g. garbage collection (~fre(0)),
where both variables are moved together and the relationship
V:a&=V:b& holds true.