Menu

#838 "Redim Preserve" not preserving array data for UDT array

closed
nobody
compiler
2019-09-15
2016-10-14
Dr. MAD
No

using the "preserve" option on Redim does not retain all of the information in the array if it is a User Defined Type.

Type chord
    x as UByte
    y as UByte
End Type

Redim a(0, 0) as chord
Dim i as UByte
Dim i2 as UByte
Dim ArrayMax1 as UByte = 0
Dim ArrayMax2 as Ubyte = 0

For i = 1 to 4
    For i2 = 1 to 4
        If ArrayMax1 < i Then
            Redim Preserve a(0 to i, 0 to ArrayMax2)
            ArrayMax1 = i
        End If
        If ArrayMax2 < i2 Then
            Redim Preserve a(0 to ArrayMax1, 0 to i2)
            ArrayMax2 = i2
        End If
        a(i,i2).x = i
        a(i,i2).y = i2
    Next i2
Next i

'Display Results
For i = 1 to 4
    For i2 = 1 to 4
        Print "a(" & i & ", " & i2 & ").x :" & a(i, i2).x & " | Should = " & Str(i)
        Print "a(" & i & ", " & i2 & ").y :" & a(i, i2).y & " | Should = " & Str(i2)
    Next i2
Next i

Sleep

Results for a(1,1), a(1,2) and a(1,3) are incorrect.

I've narrowed it down to the Redim Preserve functions in other trials.

Discussion

  • fxm (freebasic.net)

    Have you seen this note in documentation about Preserve:

    ReDim Preserve may not work as expected in all cases:
    Preserve's current behavior is to keep the original data contiguous in memory, and only expand or truncate the size of the memory.
    Its behavior is only well-defined when the upper bound is changed. If the lower bound is changed, the current result is that the data is in effect shifted to start at the new lower bound.
    If there are multiple dimensions, only the upper bound of the first dimension may be changed safely. If lower-order dimensions are resized at all, the effects can be hard to predict.

    This behavior (only the upper bound of the first dimension can be changed safely) is because multidimensional arrays are stored in this definite order:
    Values differing only in the last index are contiguous (row-major order).

     

    Last edit: fxm (freebasic.net) 2016-10-14
  • Dr. MAD

    Dr. MAD - 2016-10-14

    I have. But unless I'm mistaken, the lower bounds (0) stays consistant and is never touched. I've even tried removing the lower bounds designation from the Redim statement. To no avail.

    I think because it has another layer of dimensioning, (Being a UDT) it confuses Redim.

    I've been looking at this for a while, but I think I'm going to look at it some more over the weekend.

    I hope someone else will too if they get the chance. I apreciate the helps.

     
  • fxm (freebasic.net)

    In order to preserve the current values of the array, the only upper bound of the first dimension can be modified (the other 3 bounds of your array must not been modified).

    More generally whatever the array type (predefined datatype or specific UDT), in the instruction line:
    Redim Preserve array(z1 To z2, y1 To y2, x1 To x2)
    only the value of z2 (the upper bound of the first dimension) can be modified to safely preserve the former values of the addresses still accessible of the resized array.

    That is because multidimensional arrays are arranged in row-major order (data with consecutive last index are contiguous in memory), and Redim Preserve does not reposition any data in memory, It only appends or removes from the end.

     

    Last edit: fxm (freebasic.net) 2016-10-15
  • Dr. MAD

    Dr. MAD - 2016-10-15

    Got it.

    So to expand an array beyond just the value of the z2 one can create a secondary Redim array equal to the size of the first, backup the first into the second, redim the first to the new(bigger) size and then restore the backedup values from the second to the first.

    That is the way I've had to work around this. But it sounds like that is just they way it needs to be done.

    Thanks again for the help.

     
  • Jeff Marshall

    Jeff Marshall - 2019-09-15
    • status: open --> closed
     
  • Jeff Marshall

    Jeff Marshall - 2019-09-15

    Yes, this is expected behaviour as documented at https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgRedim

    Thanks, Dr. MAD
    Thanks, fxm

     

Log in to post a comment.