Menu

Issues with passing array elements by Var and variable naming in calling recursive procedures

2019-06-04
2019-06-07
  • Yet Another Troll

    Seen in xbasic 1.25-50 on an Android 5.1.1 device. Arrays appear to become corrupt after passing an element by Var to a procedure which modifies it. Passing variables by Var to a recursive procedure become corrupt when that procedure modifies them and uses the same variable names to refer to different variables. I have yet to try this in Windows or Linux.

    I'm going to need more coffee.

    ' X11-Basic weird quirks
    
    Program Quirks
     ' GoSub UnForgiving
     GoSub VarElements
     GoSub Recursed
     ' GoSub BigStrings
     ' GoSub RandomB0rkage
    End
    
    Procedure VarElements()
     Local X%()
     Print "VarElements"
     Dim X%(10)
     Inc X%(0)
     Dec X%(1)
     Print "X%() before", X%(0), X%(1)
     @Mov(X%(1), -666)
     Print "X%() after", X%(0), X%(1)
    Return
    
    Procedure Mov(Var Dst%, Src%)
     Print "Mov", Dst%, Src%
     Dst% = Src%
     Print "After", Dst%, Src%
    Return
    
    Procedure Recursed()
     Local X%, Y%
     Print "Recursed"
     X% = 10
     Y% = 5
     Print "Before", X%, Y%
     GoSub Recurser(Y%, X%)
     Print "After", X%, Y%
    Return
    
    Procedure Recurser(Var X%, Var Y%)
     If Y% > 0 Then
      Add X%, Y%
      Dec Y%
      GoSub Recurser(X%, Y%)
     EndIf
    Return
    

     
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-04

    Well, the way you use the VAR statement has notbeen forseen. It is ment to pass whole variables to the procedure, in this case a whole variable is the whole array and not an indexed value. (If compile the program and run it, you get an error message.)

    Maybe it should also work like that, but in this case one must consider this a bug. Maybe a better error message would do.

    The other thing (with recurser) shows a quirk in the interpreter, which just comes from the fact, that the variable names are equal. If you do following, it works as expected:

    Procedure Recursed()
     Local X%, Y%
     Print "Recursed"
     X1% = 10
     Y1% = 5
     Print "Before", X1%, Y1%
     GoSub Recurser(Y1%, X1%)
     Print "After", X1%, Y1%
    Return
    

    It comes from following:
    After having passed Y% from recursed to the procedure recurser VAR x%, the variable x% has already been overwitten and such the original y% will also be passed to y% inside the recurser procedure. So you should avoid to use the same variable names inside and outside a procedure when passed by reference. This, however is a problem with the interpreter only. If you compile the program, it works as expected. Thecompiler uses a propper stackfor parameter passing, but the interpreter does not. This could be improved.

     

    Last edit: Markus Hoffmann 2019-06-04
  • Yet Another Troll

    I was looking to use passing array elements by VAR heavily in recursive prefix tree code, similar to Introduction to Pascal course binary tree homework programs. Now that I'm trying a persistent storage based trie, the workaround will allow me to cut down on the recursive heap usage with long keys. I've also learned to be more careful with variable names that could be passed around by VAR, but what of reusable library modules designed to be merged into other people's programs, like I'm hoping with my ISAM?

    Thanks very much for your help.

     
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-05

    Hm, why not try to fix it. If you volunteer to test it...

     
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-05

    I think, I have fixed it now, both. You should be able to pass indexed array entries to normal variables inside a procedure by reference. And, also the second problem with recurser is fixed, too.

    It is in 1.25-54, but needs testing.

     
    • Yet Another Troll

      Thanks! I know just the thing to test them out as well as the FOR fix.

      Quicksort Is Optimal For Many Equal Keys
      https://arxiv.org/abs/1608.04906

      Quicksort Is Optimal
      https://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf

       
    • Yet Another Troll

      I installed the 1.26.54-unstable APK and found a problem with FOR. The N% - 1 in the first loop appears to evaluate to N%.

      Thanks again!

      #!/usr/bin/xbasic
      
      Program FatPivotQuicksort
      
       Clr M%, N%
      
       M% = 4
       N% = 10000
      
       Dim Freqs%(M% + 1)
       Dim A%(N%)
       Clr Freqs%()
       ArrayFill A%(), 0xDEADBEEF
      
       For i% = N% - 1 To N% * 0 - 1 + 1 Step 0 * N% - 1
        Print Chr$(13); i%; "   ";
        j% = Random(M%) ! May return M%
        A%(i%) = j%
        Inc Freqs%(j%)
       Next i%
       Print
      
       For i% = 0 To UBound(Freqs%()) - 1
        Print i%, Freqs%(i%)
       Next i%
      
       Clr lo%, hi%, Depth%, Start
       lo% = 0
       hi% = UBound(A%()) - 1
       Start = Timer
       Print "Sorting..."
       GoSub Quicksort(A%(), lo%, hi, 0, Depth%)
       Print "Sorted in "; Timer - Start
       Print "Call depth "; Depth%, lo%, hi%
      
       For i% = 0 To N% - 1
        Dec Freqs%(A%(i%))
       Next i%
      
       For i% = 0 To UBound(Freqs%()) - 1
        Print i%, Freqs%(i%)
       Next i%
      
       For i% = 1 To N% - 1
        If Not (A%(i% - 1) <= A%(i%)) Then
         Print "A%() out of order"
         Stop
        EndIf
       Next i%
      
       Print "OK"
      
      End
      
      Procedure Median3(Var lo%, Var me%, Var hi%)
       ' Any of lo%, me%, hi% could be aliased
       If Not (lo% <= me%) Then
        Swap lo%, me%
       EndIf
       If Not (lo% <= hi%) Then
        Swap lo%, hi%
       EndIf
       If Not (me% <= hi%) Then
        Swap me%, hi%
       EndIf
      Return
      
      Procedure Quicksort(Var A%(), lo%, hi%, Depth%, Var MaxDepth%)
       local i%, j%
       Inc Depth%
       If Depth% > MaxDepth% Then
        MaxDepth% = Depth%
       EndIf
       @Median3(A%(lo%), A%(hi%), A%(lo% + ((hi% - lo%) Div 2)))
      Return
      
       
      • Markus Hoffmann

        Markus Hoffmann - 2019-06-05

        I have fixed this issue now (FOR/NEXT with spaces). But before I recompile X11-Basic, maybe you find some more errors to be fixed.

         
    • Yet Another Troll

      Compiling appears problematic:

      This is the source code:

      #!/usr/bin/xbasic
      
      Program FatPivotQuicksort
      
       Clr M%, N%, i%, j%
      
       M% = 10
       N% = 1000000
      
       Dim Freqs%(M% + 1)
       Dim A%(N%)
       Clr Freqs%()
       ArrayFill A%(), 0xDEADBEEF
      
       For i% = (N% - 1) To N% * 0 - 1 + 1 Step 0 * N% - 1
        Print Chr$(13); i%; "   ";
        j% = Random(M%) ! May return M%
        A%(i%) = j%
        Inc Freqs%(j%)
       Next i%
       Print
      
       For i% = 0 To UBound(Freqs%()) - 1
        Print i%, Freqs%(i%)
       Next i%
      
       Clr l%, r%, Depth%, Start
       l% = 0
       r% = UBound(A%()) - 1
       Start = Timer
       Print "Sorting..."
       GoSub Quicksort(A%(), l%, r%, 0, Depth%)
       Print "Sorted in "; Timer - Start
       Print "Call depth "; Depth%, l%, r%
      
       For i% = 0 To N% - 1
        Dec Freqs%(A%(i%))
       Next i%
      
       For i% = 0 To UBound(Freqs%()) - 1
        Print i%, Freqs%(i%)
       Next i%
      
       For i% = 1 To N% - 1
        If Not (A%(i% - 1) <= A%(i%)) Then
         Print "A%() out of order"
         Stop
        EndIf
       Next i%
      
       Print "OK"
      
      End
      
      Procedure Sort3(Var x%, Var y%, Var z%)
       ' Any of l%, m%, r% could be aliased
       If Not (x% <= y%) Then
        Swap x%, y%
       EndIf
       If Not (x% <= z%) Then
        Swap x%, z%
       EndIf
       If Not (y% <= z%) Then
        Swap y%, z%
       EndIf
       Print x%, y%, z%
      Return
      
      Procedure Quicksort(Var A%(), l%, r%, Depth%, Var MaxDepth%)
       local i%, j%, k%, p%, q%, v%
      
       Inc Depth%
       If Depth% > MaxDepth% Then
        MaxDepth% = Depth%
       EndIf
      
      TailCallElimination:
      
       If Not (l% < r%) Then
        GoTo DijkstraWouldNotLikeThis
       EndIf
      
       ' Corrupt program structure warning here
       ' Exit If (Not (l% < r%))
      
       Print l%, r%,
      
       @Sort3(A%(l%), A%(r%), A%(l% + ((r% - l%) Div 2)))
      
       i% = l% - 1
       j% = r%
       p% = l% - 1
       q% = r%
       v% = A%(r%)
      
       Do
        Do
         Inc i%
         Exit If Not (A%(i%) < v%)
        Loop
        Do
         Dec j%
         Exit If Not (v% < A%(j%))
         Exit If j% = l%
        Loop
        Exit If Not (i% < j%)
        Swap A%(i%), A%(j%)
        If A%(i%) = v% Then
         Inc p%
         Swap A%(p%), A%(i%)
        EndIf
        If v% = A%(j%) Then
         Dec q%
         Swap A%(j%), A%(q%)
        EndIf
       Loop
       Swap A%(i%), A%(r%)
       j% = i% - 1
       i% = i% + 1
       k% = l%
       While k% < p%
        Swap A%(k%), A%(j%)
        Inc k%
        Dec j%
       Wend
       k% = r% - 1
       While k% > q%
        Swap A%(i%), A%(k%)
        Dec k%
        Inc i%
       Wend
       @Quicksort(A%(), l%, j%, Depth%, MaxDepth%)
       @Quicksort(A%(), i%, r%, Depth%, MaxDepth%)
      DijkstraWouldNotLikeThis:
      Return
      
       
      • Markus Hoffmann

        Markus Hoffmann - 2019-06-05

        I tested this program. The fixed version gives following output when run interpretted (not compiled):

        0        
        0       100016
        1       99912
        2       99720
        3       100144
        4       100198
        5       100247
        6       99943
        7       99658
        8       100128
        9       100034
        10      0
        Sorting...
        0       999999  1       1       8
        0       100016  0       0       0
        100014  100016  0       0       1
        100015  100016  1       0       1
        199927  999999  3       3       7
        199927  299648  2       2       2
        199927  199928  2       1       2
        299646  299648  2       2       3
        299647  299648  3       2       3
        399791  999999  6       7       8
        399791  700180  4       4       6
        399791  399792  4       3       4
        499989  700180  5       5       6
        499989  499990  5       4       5
        600236  700180  6       6       6
        600236  600237  6       5       6
        700178  700180  6       6       7
        700179  700180  7       6       7
        799837  999999  9       9       9
        799837  899966  8       8       8
        799837  799838  8       7       8
        899965  899966  9       8       9
        Sorted in 82.64433002472
        Call depth 9    0       999999
        0       0
        1       0
        2       0
        3       0
        4       0
        5       0
        6       0
        7       0
        8       0
        9       0
        10      0
        OK
        
         
        • Markus Hoffmann

          Markus Hoffmann - 2019-06-05

          However, when I run the compiled version:

          0        
          0       100016
          1       99912
          2       99720
          3       100144
          4       100198
          5       100247
          6       99943
          7       99658
          8       100128
          9       100034
          10      0
          Sorting...
          0       999999  ERROR at offset $277: Incorrect parameter,  must be number
          
          2 parameters:
           0:  <array(),3,A>
           1:  <array(),3,A>
          

          ... need to work on that...

           
          • Yet Another Troll

            There is another issue with the interpreter when I put the original parameter names l%, m%, and r% back into Sort3 and it is called in such a way that two or more arguments are actually the same array element. I also get corrupt program structure warnings when I try to use EXIT IF to leave Quicksort early, which is why I resorted to GOTO.

            See the line beginning with 40032,

            #!/usr/bin/xbasic
            
            Program FatPivotQuicksort
            
             Clr M%, N%, i%, j%
            
             M% = 10
             N% = 100000
            
             Dim Freqs%(M% + 1)
             Dim A%(N%)
             Clr Freqs%()
             ArrayFill A%(), 0xDEADBEEF
            
             For i% = (N% - 1) To N% * 0 - 1 + 1 Step 0 * N% - 1
              Print Chr$(13); i%; "   ";
              j% = Random(M%) ! May return M%
              A%(i%) = j%
              Inc Freqs%(j%)
             Next i%
             Print
            
             For i% = 0 To UBound(Freqs%()) - 1
              Print i%, Freqs%(i%)
             Next i%
            
             Clr l%, r%, Depth%, Start
             l% = 0
             r% = UBound(A%()) - 1
             Start = Timer
             Print "Sorting..."
             GoSub Quicksort(A%(), l%, r%, 0, Depth%)
             Print "Sorted in "; Timer - Start
             Print "Call depth "; Depth%, l%, r%
            
             For i% = 0 To N% - 1
              Dec Freqs%(A%(i%))
             Next i%
            
             For i% = 0 To UBound(Freqs%()) - 1
              Print i%, Freqs%(i%)
             Next i%
            
             For i% = 1 To N% - 1
              If Not (A%(i% - 1) <= A%(i%)) Then
               Print "A%() out of order"
               Stop
              EndIf
             Next i%
            
             Print "OK"
            
            End
            
            Procedure Sort3(Var l%, Var m%, Var r%)
             ' Any of l%, m%, r% could be aliased
             If Not (l% <= m%) Then
              Swap l%, m%
             EndIf
             If Not (l% <= r%) Then
              Swap l%, r%
             EndIf
             If Not (m% <= r%) Then
              Swap m%, r%
             EndIf
            Return
            
            Procedure Quicksort(Var A%(), l%, r%, Depth%, Var MaxDepth%)
             local i%, j%, k%, p%, q%, v%
            
             Inc Depth%
             If Depth% > MaxDepth% Then
              MaxDepth% = Depth%
             EndIf
            
            TailCallElimination:
            
             If Not (l% < r%) Then
              GoTo DijkstraWouldNotLikeThis
             EndIf
            
             ' Corrupt program structure warning here
             ' Exit If (Not (l% < r%))
            
             Print l%, r%,
            
             Print A%(l%); " "; A%(r%); " "; A%(l% + ((r% - l%) Div 2)),
             @Sort3(A%(l%), A%(r%), A%(l% + ((r% - l%) Div 2)))
             Print A%(l%); " "; A%(r%); " "; A%(l% + ((r% - l%) Div 2))
            
             i% = l% - 1
             j% = r%
             p% = l% - 1
             q% = r%
             v% = A%(r%)
            
             Do
              Do
               Inc i%
               Exit If Not (A%(i%) < v%)
              Loop
              Do
               Dec j%
               Exit If Not (v% < A%(j%))
               Exit If j% = l%
              Loop
              Exit If Not (i% < j%)
              Swap A%(i%), A%(j%)
              If A%(i%) = v% Then
               Inc p%
               Swap A%(p%), A%(i%)
              EndIf
              If v% = A%(j%) Then
               Dec q%
               Swap A%(j%), A%(q%)
              EndIf
             Loop
             Swap A%(i%), A%(r%)
             j% = i% - 1
             i% = i% + 1
             k% = l%
             While k% < p%
              Swap A%(k%), A%(j%)
              Inc k%
              Dec j%
             Wend
             k% = r% - 1
             While k% > q%
              Swap A%(i%), A%(k%)
              Dec k%
              Inc i%
             Wend
             @Quicksort(A%(), l%, j%, Depth%, MaxDepth%)
             @Quicksort(A%(), i%, r%, Depth%, MaxDepth%)
            DijkstraWouldNotLikeThis:
            Return
            
             
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-06

    Hm, NAK: The program worked fine (with new X11-Basic in interpreter). No errors.

     
    • Yet Another Troll

      Could it be Android specific? I'll continue to poke at it. Still, thank you very much for your help.

       
      • Markus Hoffmann

        Markus Hoffmann - 2019-06-06

        Try to use the new version 1.26-55 it is out now. Maybe this issue was (accidentally) fixed.

         
        • Yet Another Troll

          It's still happening for me in the 1.26-55-unstable.apk. The Quicksort routine is now at least as much test harness rigging than algorithm. Most of the bugs and variable name typos so far have been in the debug cruft. I really miss OPTION EXPLICIT and DEFOBJ A-Z from VBA and 1990s Visual Basic.

          #!/usr/bin/xbasic
          
          Program MedianOf3FatPivotQuicksort
          
           Print "Quicksort is Optimal..."
          
           Clr M%, N%, i%, j%
          
           M% = 10
           N% = 100000
          
           Dim Freqs%(M% + 1)
           Dim A%(N%)
           Clr Freqs%()
           ArrayFill A%(), 0xDEADBEEF
          
           For i% = N% - 1 To N% * 0 - 1 + 1 Step 0 * N% - 1
            If (i% And 0xFFF) = 0 Then
             Print Chr$(13); i%; " ";
            EndIf
            j% = Random(M%) ! May return M%
            A%(i%) = j%
            Inc Freqs%(j%)
            If (i% And 0xFFF) = 0 Then
             Print "  "; j%; "  "; A%(i%); "  "; Freqs%(j%); Space$(8);
             Flush
            EndIf
           Next i%
           Print
          
           For i% = 0 To UBound(Freqs%()) - 1
            Print i%, Freqs%(i%)
           Next i%
           Flush
          
           Clr l%, r%, Depth%, Start
           l% = 0
           r% = UBound(A%()) - 1
           Start = Timer
           Print "Sorting..."
           Flush
           GoSub Quicksort(A%(), l%, r%, 0, Depth%)
           Print "Sorted in "; Round(Timer - Start, 2); " s, "; 
           Print Round(N% / (Timer - Start), 2); " elements/s"
          
           Print "Call depth "; Depth%, l%, r%
           Flush
          
           For i% = 0 To N% - 1
            Dec Freqs%(A%(i%))
            If i% = 0 Then
             ! No-op
            Else If Not (A%(i% - 1) <= A%(i%)) Then
             Print "A%() out of order", i% - 1, i%, A%(i% - 1), A%(i%)
             Stop
            EndIf
           Next i%
          
           For i% = 0 To UBound(Freqs%()) - 1
            Print i%, Freqs%(i%)
           Next i%
          
           Print "OK"
          
          End
          
          Procedure Sort3(Var l%, Var m%, Var r%)
           ' Any of l%, m%, r% could be aliased
           Print l%; " "; m%; " "; r%,
           If Not (l% <= m%) Then
            Swap l%, m%
           EndIf
           If Not (l% <= r%) Then
            Swap l%, r%
           EndIf
           If Not (m% <= r%) Then
            Swap m%, r%
           EndIf
           Print l%; " "; m%; " "; r%,
          Return
          
          Procedure Quicksort(Var A%(), l%, r%, Depth%, Var MaxDepth%)
           local i%, j%, k%, p%, q%, v%
          
           Inc Depth%
           If Depth% > MaxDepth% Then
            MaxDepth% = Depth%
           EndIf
          
          ' Dijkstra would not have liked this
          TailCallElimination:
          
           If Not (l% < r%) Then
            ! No-op 
          
           Else If 0 ! r% - l% < 3 Then
            ' Should short but non-trivial runs be sorted using a simpler
            ' algorithm like insertion sort to avoid median of three
            ' fat pivot qsort's overhead where we don't really need it?
          
            Select r% - l%
             Case 1
              Print l%, r%, "Swap2",
          
              Print A%(l%); " "; A%(r%),
          
              p% = A%(l%) + A%(r%)
              q% = A%(l%) Xor A%(r%)
          
              If Not (A%(l%) <= A%(r%)) Then
               Swap A%(l%), A%(r%)
              EndIf
          
              Print A%(l%); " "; A%(r%)
          
              If (Not (A%(l%) <= A%(r%)))       \
                 Or (p% <> (A%(l%) + A%(r%)))   \
                 Or (q% <> (A%(l%) Xor A%(r%))) Then
               Print "Swap2 Fail"
               Stop
              EndIf
          
             Case 2
              Print l%, r%, "Sort3",
          
              Print A%(l%); " "; A%(l% + 1); " "; A%(r%),
          
              p% = A%(l%) + A%(l% + 1) + A%(r%)
              q% = A%(l%) And A%(l% + 1) And A%(r%)
          
              @Sort3(A%(l%), A%(l% + 1), A%(r%))
          
              Print A%(l%); " "; A%(l% + 1); " "; A%(r%)
          
              If (Not ((A%(l%) <= A%(l% + 1)) And (A%(l% + 1) <= A%(r%)))) \
                 Or (p% <> (A%(l%) + A%(l% + 1) + A%(r%)))     \
                 Or (q% <> (A%(l%) And A%(l% + 1) And A%(r%))) Then
               Print "Sort3 Fail"
               Stop
              EndIf
          
             Default
              ' Alternative sorting method goes here
              Print l%, r%, "???", r% - l%
              Stop
            EndSelect
          
           Else
          
            Print l%, r%, "Qsort",
          
            ' Consider choosing random element between l% and r%
            k% = l% + ShR(r% - l%, 1) ! >> 1)
            p% = A%(l%) + A%(k%) + A%(r%)
            q% = A%(l%) And A%(k%) And A%(r%)
          
            If Not ((l% <= k%) And (k% <= r%)) Then
             Print "Binary chop Fail", l%, k%, r%
             Stop
            EndIf
          
            Print A%(l%); " "; A%(r%); " "; A%(k%),
          
            @Sort3(A%(l%), A%(r%), A%(k%))
          
            Print A%(l%); " "; A%(r%); " "; A%(k%)
          
            If (Not ((A%(l%) <= A%(r%)) And (A%(r%) <= A%(k%)))) \
               Or (p% <> (A%(l%) + A%(k%) + A%(r%)))     \
               Or (q% <> (A%(l%) And A%(k%) And A%(r%))) Then
             Print "VAR recursive reused variable aliased array element nightmare Fail"
             Stop
            EndIf
          
            k% = 0xDEADBEEF
            p% = 0xDEAFBEEF
            q% = 0xDEAFBEEF
          
            i% = l% - 1
            j% = r%
            p% = l% - 1
            q% = r%
            v% = A%(r%)
          
            Do
             Repeat
              Inc i%
             Until Not (A%(i%) < v%)
             Repeat
              Dec j%
              ' Can we use the Sort3 call to let us use A%(l%)
              ' as a sentinel and get rid of the j% = l% test?
              ' Exit If Not (v% < A%(j%))
              ' Exit If j% = l%
              ' If j% = l% Then
              '  Print l%, j%, v%, A%(l%)
              '  Stop
              ' EndIf
             Until Not (v% < A%(j%))
             If j% < l% Then
              Print "Out of bounds!", l%, i%, j%, r%, v%
              Stop
             EndIf
             Exit If Not (i% < j%)
             Swap A%(i%), A%(j%)
             If A%(i%) = v% Then
              Inc p%
              Swap A%(p%), A%(i%)
             EndIf
             If v% = A%(j%) Then
              Dec q%
              Swap A%(j%), A%(q%)
             EndIf
            Loop
            Swap A%(i%), A%(r%)
            j% = i% - 1
            i% = i% + 1
            k% = l%
            While k% < p%
             Swap A%(k%), A%(j%)
             Inc k%
             Dec j%
            Wend
            k% = r% - 1
            While k% > q%
             Swap A%(i%), A%(k%)
             Dec k%
             Inc i%
            Wend
            @Quicksort(A%(), l%, j%, Depth%, MaxDepth%)
            l% = i%
            GOTO TailCallElimination
            Print "DEAD CODE"
            Stop
            @Quicksort(A%(), i%, r%, Depth%, MaxDepth%)
           EndIf
          Return
          
           

          Last edit: Yet Another Troll 2019-06-06
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-07

    Hm, I see. So there are no Interpretererrrors, no crashes, but the calculation result is not correct?
    Can we have a more simple example which produces the error? Otherwise it is very hard for me to track it down.

     
    • Yet Another Troll

      I'll certainly try, but simple snippets aren't reproducing the issue. A simple snippet that does produce an interpreter crash is this, due to missing commas in PRINT statements, which had me chasing my tail for a while before I found it,

      Procedure BigStrings()
       Local A$, B$, VPA%, VPB%
      
       Print "Clearing"
       Clr A$, B$, VPA%, VPB%
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%, VPB%
       ' Print VarPtr(A$), VarPtr(B$)
       Pause 5
      
       Print "Assigning A"
       A$ = Space$(1000)
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%, VPB%
       ' Print VarPtr(A$), VarPtr(B$)
       Pause 5
      
       Print "Assigning B"
       B$ = A$
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%, VPB%
       ' Print VarPtr(A$), VarPtr(B$)
       Pause 5
      
       Print "Mangling A"
       Poke VPA%, Asc("A")
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%, VPB%
       ' Print VarPtr(A$), VarPtr(B$)
       Pause 5
      
       Print "Display"
       Print Left$(A$, 5), Left$(B$, 5)
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%  VPB%
       ' Print VarPtr(A$), VarPtr(B$)
       Pause 5
      
       Print "Cleanup"
       Clr A$, B$
       VPA% = VarPtr(A$)
       VPB% = VarPtr(B$)
       Print VPA%, VPB%
       Print VarPtr(A$)  VarPtr(B$)
       Pause 5
      
       Print "Return"
      Return
      
       
  • Markus Hoffmann

    Markus Hoffmann - 2019-06-07

    Confirmed. The error causes the interpreter to crash. Shame on me. I am working on a fix.

     
    • Yet Another Troll

      One thing I found strange was that the B$ = A$ assignment appears to cause VARPTR(A$) to change well before the bad PRINT statements and the crash.

       
      • Markus Hoffmann

        Markus Hoffmann - 2019-06-07

        I cannot confirm that:

        Clearing
        35421840        35421984
        Assigning A
        35424400        35421984
        Assigning B
        35424400        35425424
        Mangling A
        35424400        35425424
        Display
        A            
        0
        Cleanup
        35424400        35425424
        ERROR: Syntax error: missing closing parenthesis in <A$) VARPTR(B$>.
        ERROR at line 51: Illegal variable name A$) VARPTR(B$. can not create.
        0
        
         
    • Markus Hoffmann

      Markus Hoffmann - 2019-06-07

      I have fixed it now. It will be in 1.25-56.

       
      • Yet Another Troll

        Awesome, thanks! I think I saw the address of a string variable change unexpectedly before, but it could have merely been a hallucination from too much coffee, or perhaps not enough coffee, it's difficult to tell sometimes. However, it was that which got me wondering about reference counted strings. It would certainly eliminate the temptation to pass very long strings by VAR solely for a bit of speed, but interactions with VARPTR, POKE, perhaps ABSOLUTE, lvalue MID$ support, and passing strings to C routines would become tricky.

         

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.