|
Post by dragonjim on Sept 11, 2012 14:00:11 GMT 1
The Redim command seems to work correctly for both simple and type arrays under Option Base 0, but when Option Base 1 is used, something odd occurs the first time you 'Redim' the original dimension, as can be seen from the following code:
Option Base 1 OpenW 1 Dim a(10), n For n = 1 To 10 : a(n) = n : Next n ReDim a(20) For n = 11 To 20 : a(n) = n : Next n ReDim a(30) For n = 1 To 20 Print a(n) Next n Do Sleep Until Win_1 Is Nothing
As you will see, the first ten elements entered before the first Redim have been shifted up one and element 10 is now empty. However, elements 11-20 seem unaffected by the second Redim (Redim a(30)).
The workaround? Dim the array, then immediately Redim it BEFORE entering data,as below:
Option Base 1 OpenW 1 Dim a(10), n ReDim a(10) For n = 1 To 10 : a(n) = n : Next n ReDim a(20) For n = 11 To 20 : a(n) = n : Next n ReDim a(30) For n = 1 To 20 Print a(n) Next n Do Sleep Until Win_1 Is Nothing
This seems to get around the bug...so far.
|
|
|
Post by 649psoft2 on Sept 21, 2012 9:11:10 GMT 1
Halloo dragonjim,
To be reminded ReDim does not erase an array.
From the help file:
"ReDim doesn't erase the array. To explicitly erase an array use Erase."
Therefore the values should be cleared or reassigned after ReDim(). This is a little extra work the command could have had additional handling.
Also where possible a variable type should be explicitly declared.
Since a type was not declared the a() array (not a|(0), a&(), or as Byte or As Word etc, for numerical types of variables) Gfa Basic 32 automatically defaulted your array to a 16 byte type variant array.
From the help file:
" Note A variant always takes up 16 bytes, no matter what you store in it. Objects, strings, and arrays are not physically stored in the Variant; in these cases, four bytes of the Variant are used to hold either an object reference, or a pointer to the string or array. The actual data are stored elsewhere. "
A variant can change to different types with a lot of internal and automatic handling by GB32.
To show that it is not exactly the same array and not in the same place:
Option Base 1
OpenW 1 Dim a(10), n
'where is the first element? MsgBox V:a(1)
Global adr1% = V:a(1)
For n = 1 To 10 : a(n) = n : Next n For n = 1 To 10 : Print a(n); V:a(n) : Next n
'Erase a() 'should be used so as not to permit 2 'arrays of the name a(), though they 'are in fact copied to different locations 'with each declaration
ReDim a(20)
'where is the first element? MsgBox V:a(1)
Do : Sleep : Until Win_1 Is Nothing
I have run in to some memory issues I think due to the compiler using backward to 16 bit for very large arrays:
This is my theory:
The original array space stays resident (possibly to orient and stabilize the interpreter with successive runs until the freeing of all arrays and objects with a proper program close and cleanup). At any rate the developers probably patched the ReDim() command the backward compatibility to 16 bit and 32 bit differing memory models I suspect had compiler oddities at the time.
With 32 bit the API Memory allocation is more stable in larger memory allocations though I have found cAlloc() to work effectively so far but not in all cases Dim and ReDim for arrays.
|
|
|
Post by dragonjim on Sept 30, 2012 16:00:04 GMT 1
Thank you for your response and comments. The Redim command gives a program so much more potential - gone are the days when you have to restrict the number of records that a program can store! - that it is annoying that there are small bugs in its operation...and even more annoying that it doesn't handle multi-element arrays!
I take on board your comments about the undefined array type; however, I can confirm that the bug occurs - and the solution fixes - all the variable types that I have tried, including user-defined TYPE arrays.
In reference to the erasing of data, I possibly wasn't very clear - my wish was to have the data retained while I popped on a few more elements to expand it. Generally, if I am looking to completely reconstitute an array from scratch I always find it is better, as you mentioned, to use the ERASE command and then DIM anew - otherwise you can inherit 'ghost' values from the old array which can lead to some interesting debugging sessions!
|
|
|
Post by 649psoft2 on Oct 15, 2012 19:02:07 GMT 1
This is a wish I and also wish there was more extensive handing in this case and there is no warning of the error.
There are a lot of things to wish for in all languages both high and low level.
This is an annoyance but I would classify it as an easy to make error since array memory can also be overwritten without explicit re-allocation in assembly and other low level languages.
Many high level languages are very limited in flexblity in the tradeoff for ease of use and often have a "black box" or inaccessable approch to their handled commands.
The case with the memory allocation in the interpreter without the memory being explicitly released before exiting each run (as in the "C" native MS Win 32) (set object = nothing or erase&() or the API ~Delete()) has not been fully defined and in some cases not fully handled on cleanup it seems.
Win 32 objects have limitations to this day as I found that the Win32 listview does not support more than 16 million elements or 16 MB memory at one set of data.
The older GFA arrays can have up to seven dimensions but I think the multiple of the elements cannot exceed 64k. A one dimentional byte array is the exception and I have not found any limit with a|().
You have to initatiate a new array beyond this or have a storage place for the data just as you do when reaching the limitation of the Win32 subsystem listview dimensional and memory limitations.
|
|
|
Post by dragonjim on Oct 19, 2012 17:09:58 GMT 1
I understand what you say above High-level languages - I can vaguely remember Atari's 1st Basic: that was fun! That said, GFA Basic is better than most I have tried although, sadly, it seems to be dying a slow death as the activity on this forum shows (I am aware of the email polling system - not too sure why most of the activity is hidden from any new prospective programmers interested in the language).
Just to finish my comments on ReDim: Again with Option Base 1 only, if an array is ReDim'ed, then QSort no longer works correctly when a second integer array is used, as in the following example:
Option Base 1 OpenW 1 : Win_1.AutoRedraw = 1 Dim drag$(30), drag2$(10), dr%(30) ReDim drag2$(30) Local n As Int16 For n = 1 To 30 drag$(n) = "Dragon" & n drag2$(n) = "Dragon" & n Next n QSort drag$(), 30, dr%() QSort drag2$(), 30, dr%() For n = 1 To 30 Print AT(1, n); drag$(n), drag2$(n) Next n QSort drag$() : QSort drag2$() For n = 1 To 30 Print AT(60, n); drag$(n), drag2$(n) Next n Do Sleep Until Win_1 Is Nothing
The only option? Well, except for using Option Base 0 - which has its own related QSort bug - don't ReDim.
|
|