Mega Search
23.2 Million


Sign Up

Make a donation  
Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general

Hi all,

Just a quick query - which is better, in terms of speed and memory 
usage: a static or a dynamic array.

For example, consider

  data: array[0..819200] of Byte;

where we might only use 9760 bytes on some occasions, but may use the 
full 819200 on others, or:

  data: array of Byte;

and then SetLength(data,9760) or SetLength(data,819200)...or any other 
size, depending on the size of the file being loaded. I know these days, 
800KB in nothing (when most PCs have in excess of 1GB of RAM).

Cheers,

Gerald.

Vote for best question.
Score: 0  # Vote:  0
Date Posted: 14-Jan-2015, at 12:26 AM EST
From: Gerald Holdsworth
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
On 21/01/2015 20:01, Tom Brunberg wrote:
> Gerald Holdsworth wrote:


>> Here is what I've found:
>>
>> * With 'data' as a global, public, dynamic array, it gets corrupted;
>> * if I change it back to a static array (and obviously remove the
>> SetLength call), it all works fine;
>> * if I move it into the procedure, so it is now local, but dynamic, and
>> call the second procedure with 'data' as a parameter (as you suggest
>> Tom, and as I've tried before, but with the array as a global dynamic),
>> it works.
>
> Gerald,
> What you say above makes no sense at all. The *only* possible difference in accessing static arrays
> versus dynamic arrays, is that dynamic arrays always have a zero based index (first element has
> index 0), while static arrays are indexed according the type declaration (e.g. array[1..77]. Since
> you in earlier post talked about array[0..819200] this is not the reason.
>
> You are definitely doing something wrong.

I've been over the code, many times - I can't see what might be causing 
it. However, with that said, I have noticed before that declaring a 
static array then going past it's boundary never caused an error, but 
did cause another array to become corrupt - that took a lot of looking 
for. So, you can see why I'm wanting to ditch the static arrays.

> For example, after you read the data, you analyse it, how?

Just reads data - doesn't do any writing back to the array.

> What exactly goes wrong in that anaysis that leads to rejection?

The app loads data files, which were used by retro software, and 
displays the graphic representation on the screen. When the array gets 
corrupted, it becomes obvious on the screen. I had thought of saving 
this bitmap (non-corrupted and corrupted) and posting it here (well, a 
link to it here), but then I got around the issue.

>
> I or anybody else do not see your screen from where we are. Guessing and speculating is a waste of
> time.

Yep - but you, and everyone else on here, have helped. And I thank you 
for that.

Cheers,

Gerald.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 22-Jan-2015, at 4:40 AM EST
From: Gerald Holdsworth
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
Gerald Holdsworth wrote:

> On 20/01/2015 16:12, Tom Brunberg wrote:
> > Gerald Holdsworth wrote:
> > 
> 
> > 
> > Gerald,
> > I can assure you, with 100% certainty, that the data in the array doesn't change by itself. I
> > suggest you step through the analysing part with F7/F8 a line at the time, verifying that it
> > does what it is supposed to do.
> 
> > 
> > Is there any other reason for the copying apart from the name issue (which isn't an issue at
> > all).  If you ditch the local variable named 'data' and instead pass the array from the
> > MainForm as a parameter to the procedure, like you did above with the disc images, you don't
> > need to copy it. And of course the procedure declares the array parameter with the name 'data'
> > here too.
> 
> Here is what I've found:
> 
> * With 'data' as a global, public, dynamic array, it gets corrupted;
> * if I change it back to a static array (and obviously remove the 
> SetLength call), it all works fine;
> * if I move it into the procedure, so it is now local, but dynamic, and 
> call the second procedure with 'data' as a parameter (as you suggest 
> Tom, and as I've tried before, but with the array as a global dynamic), 
> it works.

Gerald,
What you say above makes no sense at all. The *only* possible difference in accessing static arrays
versus dynamic arrays, is that dynamic arrays always have a zero based index (first element has
index 0), while static arrays are indexed according the type declaration (e.g. array[1..77]. Since
you in earlier post talked about array[0..819200] this is not the reason.

You are definitely doing something wrong.

> 
> Therefore, as a global dynamic array it gets corrupted, but as either a 
> static global, or a local dynamic, array it is all fine. Could this to 
> do with a previous poster who pointed out where the information is 
> stored (heap/stack) depending on whether it is a 
> static/dynamic/local/global array?

Only if you would run out of stack space, in which case you would get an error, or the program
would simply crash (stop running).

> And finally, what I did notice, is that the size of the global dynamic 
> array differed from what I set it to - e.g. I did a 
> SetLength(data,134508) and it was sized to 131127 elements (can't 
> remember the exact values).

You must be looking at different arrays or you have no clue what your program is doing. As I said
before, things do not change by them self or by some woodoo.
From where did you get the number you used in SetLength? How did you determine that the size was
different?

You really need to show the code that touches the data.

For example, after you read the data, you analyse it, how?
What exactly goes wrong in that anaysis that leads to rejection?
 
I or anybody else do not see your screen from where we are. Guessing and speculating is a waste of
time.

Cheers

-- 
Tom Brunberg
firstname.lastname@welho.com

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 21-Jan-2015, at 12:01 PM EST
From: Tom Brunberg
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
On 20/01/2015 16:12, Tom Brunberg wrote:
> Gerald Holdsworth wrote:
>

>
> Gerald,
> I can assure you, with 100% certainty, that the data in the array doesn't change by itself. I
> suggest you step through the analysing part with F7/F8 a line at the time, verifying that it does
> what it is supposed to do.

>
> Is there any other reason for the copying apart from the name issue (which isn't an issue at all).
> If you ditch the local variable named 'data' and instead pass the array from the MainForm as a
> parameter to the procedure, like you did above with the disc images, you don't need to copy it. And
> of course the procedure declares the array parameter with the name 'data' here too.

Here is what I've found:

* With 'data' as a global, public, dynamic array, it gets corrupted;
* if I change it back to a static array (and obviously remove the 
SetLength call), it all works fine;
* if I move it into the procedure, so it is now local, but dynamic, and 
call the second procedure with 'data' as a parameter (as you suggest 
Tom, and as I've tried before, but with the array as a global dynamic), 
it works.

Therefore, as a global dynamic array it gets corrupted, but as either a 
static global, or a local dynamic, array it is all fine. Could this to 
do with a previous poster who pointed out where the information is 
stored (heap/stack) depending on whether it is a 
static/dynamic/local/global array?

Also, even though the array is now local, do I still need to do a 
'data:=Nil;' at the end of the function - I've actually just added it, 
prior to making it local, to tidy things up. I'm assuming I can now 
safely remove it as closing the procedure will free it up anyway.

And finally, what I did notice, is that the size of the global dynamic 
array differed from what I set it to - e.g. I did a 
SetLength(data,134508) and it was sized to 131127 elements (can't 
remember the exact values).

Well, it looks like we got there, but raised some fresh questions. Thank 
you Jeff and Tom.

Cheers,

Gerald.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 9:01 AM EST
From: Gerald Holdsworth
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
Gerald Holdsworth wrote:

> On 19/01/2015 20:39, Tom Brunberg wrote:
> > > 
> 
> > 
> > We first need to know exactly what the problem is. Then I'm sure we can find a cure.
> 
> Yep, it's a difficult one to explain. I can stop the execution after the 
> file is read in, and 'hover' over the array and it looks fine, but when 
> it is analysed, the incorrect information is given meaning that the, 
> otherwise OK, file is rejected.

Gerald,
I can assure you, with 100% certainty, that the data in the array doesn't change by itself. I
suggest you step through the analysing part with F7/F8 a line at the time, verifying that it does
what it is supposed to do.

> After the file is read into the array, it may be passed to another 
> procedure, depending on it's extension (what that is, is not important). 
> I have three functions, for reading in old retro disc images of 
> different formats. One of the declarations is:
> 
> function readDFSDisc(var data: array of Byte;format: String): TDisc;
> 
> I call this function by disc:=readDFSDisc(data,'.ssd');

The above is correct.

> Should this be, in this case, disc:=readDFSDisc(data[0],'.ssd');  ?
> (and the same for the other, similar, functions)
> Incidentally, 'data' does not get altered in any way within these functions.
> 
> However, there are other circumstances where the file loaded is not a 
> retro disc image, but an actual retro data file. This is not accessed by 
> this procedure, but by another in another unit (hence why 'data' is 
> public). The first thing this other procedure does is to copy the 
> information from one array to another (local to the procedure, but also 
> dynamic...but static also has the same effect):
> 
>     for x:=0 to MainForm.fsize-1 do
>      data[x]:=MainForm.data[x];
> 
> (this is easier than changing the huge number of occurrences of the 
> local 'data' to MainForm.data...and there is probably an easier way of 
> copying said array - Copy method perhaps?)

Is there any other reason for the copying apart from the name issue (which isn't an issue at all).
If you ditch the local variable named 'data' and instead pass the array from the MainForm as a
parameter to the procedure, like you did above with the disc images, you don't need to copy it. And
of course the procedure declares the array parameter with the name 'data' here too.

> As I said, it is difficult to explain without actually showing you in 
> person. However, if I have a brainwave on a better way to illustrate it, 
> I'll do it.

Actual code explains more than a thousand word (hmmm ... I've heard that before ...).

Regards
Tom

-- 
Tom Brunberg
firstname.lastname@welho.com

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 8:12 AM EST
From: Tom Brunberg
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
On 19/01/2015 20:39, Tom Brunberg wrote:
>>

>
> We first need to know exactly what the problem is. Then I'm sure we can find a cure.

Yep, it's a difficult one to explain. I can stop the execution after the 
file is read in, and 'hover' over the array and it looks fine, but when 
it is analysed, the incorrect information is given meaning that the, 
otherwise OK, file is rejected.

After the file is read into the array, it may be passed to another 
procedure, depending on it's extension (what that is, is not important). 
I have three functions, for reading in old retro disc images of 
different formats. One of the declarations is:

function readDFSDisc(var data: array of Byte;format: String): TDisc;

I call this function by disc:=readDFSDisc(data,'.ssd');
Should this be, in this case, disc:=readDFSDisc(data[0],'.ssd');  ?
(and the same for the other, similar, functions)
Incidentally, 'data' does not get altered in any way within these functions.

However, there are other circumstances where the file loaded is not a 
retro disc image, but an actual retro data file. This is not accessed by 
this procedure, but by another in another unit (hence why 'data' is 
public). The first thing this other procedure does is to copy the 
information from one array to another (local to the procedure, but also 
dynamic...but static also has the same effect):

    for x:=0 to MainForm.fsize-1 do
     data[x]:=MainForm.data[x];

(this is easier than changing the huge number of occurrences of the 
local 'data' to MainForm.data...and there is probably an easier way of 
copying said array - Copy method perhaps?)

As I said, it is difficult to explain without actually showing you in 
person. However, if I have a brainwave on a better way to illustrate it, 
I'll do it.

Cheers,

Gerald.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 19-Jan-2015, at 1:47 PM EST
From: Gerald Holdsworth
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
Jeff Overcash (TeamB) wrote:

> > var
> >   data: array of Byte;
> >   F: File;
> >   fsize, amt,ptr,file_size,l: Integer;
> >   file_buffer: array[0..$FFF] of Byte;
> > begin
> >   AssignFile(F,filename);
> >   Reset(F,1);
> >   fsize:=FileSize(F);
> >   file_size:=fsize;
> >   SetLength(data,fsize);
> >   ptr:=0;
> >   while file_size>0 do
> >   begin
> >    BlockRead(F,file_buffer,Length(file_buffer),amt);
> >    for l:=0 to amt-1 do
> >     data[l+ptr]:=file_buffer[l];
> >    file_size:=file_size-amt;
> >    ptr:=ptr+amt;
> >   end;
> >   CloseFile(F);
> >   AssignFile(F,filename+'test.dat');
> >   ReWrite(F,1);
> >   BlockWrite(F,data,fsize,amt);
> >   CloseFile(F);
> > end;
> 
> 
> two bugs with this line.
> 
> 1. Should be data[0].  You want to pass the start of the array, not the address 
> of the variable that points to the start of the array.
> 2. fsize is <= 0 at this point.  You decrement it in your while loop

Jeff, actually fsize has the correct value. He is using another variable, file_size as a counter.

> Changing it to
> 
>     BlockWrite(F, data[0], Length(data), amt);
> 
> worked for me.

fsize can be used here.

Cheers

-- 
Tom Brunberg
firstname.lastname@welho.com

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 19-Jan-2015, at 1:22 PM EST
From: Tom Brunberg
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
Gerald Holdsworth wrote:
> On 19/01/2015 15:02, Tom Brunberg wrote:
>> Gerald Holdsworth wrote:
>>
> 
>> Please show the procedure(s) where you load original file, create a new one (file or array?) and
>> save it to disk.
> 
> This has been concatenated for clarity. 'data' and 'fsize' are declared 
> in the public section of the Form declaration, while 'F' and 'amt' are 
> declared locally in the procedure. Also, the code is on the other 
> computer, which is currently turned off. If I change it to how Jeff 
> suggested (which is how the code now currently looks) it still works the 
> same.
> The code to save the data is only temporary, and if I access the array 
> 'data' later on (which I do), I still get the corrupted data.
> 
> var
>   data: array of Byte;
>   F: File;
>   fsize, amt,ptr,file_size,l: Integer;
>   file_buffer: array[0..$FFF] of Byte;
> begin
>   AssignFile(F,filename);
>   Reset(F,1);
>   fsize:=FileSize(F);
>   file_size:=fsize;
>   SetLength(data,fsize);
>   ptr:=0;
>   while file_size>0 do
>   begin
>    BlockRead(F,file_buffer,Length(file_buffer),amt);
>    for l:=0 to amt-1 do
>     data[l+ptr]:=file_buffer[l];
>    file_size:=file_size-amt;
>    ptr:=ptr+amt;
>   end;
>   CloseFile(F);
>   AssignFile(F,filename+'test.dat');
>   ReWrite(F,1);
>   BlockWrite(F,data,fsize,amt);
>   CloseFile(F);
> end;


two bugs with this line.

1. Should be data[0].  You want to pass the start of the array, not the address 
of the variable that points to the start of the array.
2. fsize is <= 0 at this point.  You decrement it in your while loop

Changing it to

    BlockWrite(F, data[0], Length(data), amt);

worked for me.

-- 
Jeff Overcash (TeamB)
       (Please do not email me directly unless  asked. Thank You)
And so I patrol in the valley of the shadow of the tricolor
I must fear evil. For I am but mortal and mortals can only die.
Asking questions, pleading answers from the nameless
faceless watchers that stalk the carpeted  corridors of Whitehall.
              (Fish)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 19-Jan-2015, at 1:16 PM EST
From: Jeff Overcash (TeamB)
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
> 
> Doesn't explain why the data is corrupt later on - I added this write to 
> file to see what exactly was in the array - it has nothing to do with 
> what I'm trying to do.

Well Gerald,
It certainly explains why the ...test.dat file is different from the original.

> I have since changed the read file to:
> 
> AssignFile(F,filename);
> Reset(F,1);
> fsize:=FileSize(F);
> SetLength(data,fsize);
> BlockRead(F,data[0],fsize,amt);
> CloseFile(F);
> {Code follows to analyse the data}
> 
> As suggested by Jeff. The information in the array 'data' is not the 
> same as in the file loaded.

How did you see the difference? And what exactly is different? It is not enough to say 'it is not
the same', you need to be specific when describing problems. The code suggested by Jeff seems ok to
me.

> If I change the BlockWrite to data[0], I'm 
> sure it will work, but this won't fix the problem.

We first need to know exactly what the problem is. Then I'm sure we can find a cure.

Regards

-- 
Tom Brunberg
firstname.lastname@welho.com

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 19-Jan-2015, at 12:39 PM EST
From: Tom Brunberg
 
Re: Static vs Dynamic arrays  
News Group: embarcadero.public.delphi.language.delphi.general
On 19/01/2015 20:01, Tom Brunberg wrote:
> Gerald Holdsworth wrote:
>
>> On 19/01/2015 15:02, Tom Brunberg wrote:
>>> Gerald Holdsworth wrote:
>>>
>>
>>> Please show the procedure(s) where you load original file, create a new one (file or array?) and
>>> save it to disk.
>>
>> This has been concatenated for clarity. 'data' and 'fsize' are declared
>> in the public section of the Form declaration, while 'F' and 'amt' are
>> declared locally in the procedure. Also, the code is on the other
>> computer, which is currently turned off. If I change it to how Jeff
>> suggested (which is how the code now currently looks) it still works the
>> same.
>> The code to save the data is only temporary, and if I access the array
>> 'data' later on (which I do), I still get the corrupted data.
>>
>> var
>>    data: array of Byte;
>>    F: File;
>>    fsize, amt,ptr,file_size,l: Integer;
>>    file_buffer: array[0..$FFF] of Byte;
>> begin
>>    AssignFile(F,filename);
>>    Reset(F,1);
>>    fsize:=FileSize(F);
>>    file_size:=fsize;
>>    SetLength(data,fsize);
>>    ptr:=0;
>>    while file_size>0 do
>>    begin
>>     BlockRead(F,file_buffer,Length(file_buffer),amt);
>>     for l:=0 to amt-1 do
>>      data[l+ptr]:=file_buffer[l];
>>     file_size:=file_size-amt;
>>     ptr:=ptr+amt;
>>    end;
>>    CloseFile(F);
>>    AssignFile(F,filename+'test.dat');
>>    ReWrite(F,1);
>>    BlockWrite(F,data,fsize,amt);
>>    CloseFile(F);
>> end;
>
> You have an error, which is very easy to do.
> Change 'data' in this line to 'data[0]', like this:
>>    BlockWrite(F,data[0],fsize,amt);
>
> With dynamic arrays you need to address the first item, not the array.
> A dynamic array variable is a reference (pointer) to the actual array which is elsewhere in memory.
> A static array variable is the array itself.
>
> Cheers
>
Doesn't explain why the data is corrupt later on - I added this write to 
file to see what exactly was in the array - it has nothing to do with 
what I'm trying to do.

I have since changed the read file to:

AssignFile(F,filename);
Reset(F,1);
fsize:=FileSize(F);
SetLength(data,fsize);
BlockRead(F,data[0],fsize,amt);
CloseFile(F);
{Code follows to analyse the data}

As suggested by Jeff. The information in the array 'data' is not the 
same as in the file loaded. If I change the BlockWrite to data[0], I'm 
sure it will work, but this won't fix the problem.

Cheers,

Gerald.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 19-Jan-2015, at 12:25 PM EST
From: Gerald Holdsworth