•  Back 
  •  Main 
  •  Index 
  •  Tree View 
  •  Cross references 
  •  Help 
  •  Show info about hypertext 
  •  View a new file 
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
   RETURN

   FUNCTION oh_oh
     DIM a$(10)                         ! address of local a&...
     RETURN 10                          ! in calling routine moved here
   ENDFUNC


   Some 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.