jon_rs
asked on
Delphi Dynamic Array Contiguity
I have an application that dumps data from a complicated dynamic array to disk and then reads it back in again at a later point to minimize memory usage.
The array (of singles) has four dimensions and is created in two steps:
So in others words, the first dimension is created first and then the 2nd/3rd/4th dimensions are created next because the size of the second dimension varies.
The writing to and reading from file F (file of single) is done using BlockWrite and BlockRead commands:
This assumes that the 2nd/3rd/4th dimensions of the SDVuser array are CONTIGUOUS in memory. Documentation and on-line comment that I can see on dynamic arrays suggests this is true.
But I sometimes get Range Check errors associated with the BlockRead which I am thinking might be caused by non-contiguity. I am also getting odd exceptions occurring elsewhere which again I think may be caused by memory being trampled because the array is not in fact contiguous.
Question 1: Does the SetLength para create a contiguous block of memory for the 3 dimensions I create in one go?
Question 2: Do the secondary SetLength operations cause the entire 4 dimensional structure to be recreated each time to ensue that the WHOLE array is contiguous - my observation is that assuming this causes lots more problems elsewhere and so I have avoided making this assumption.
Hope someone can clarify the situation
Best wishes
Jon
The array (of singles) has four dimensions and is created in two steps:
SetLength(SDVuser,MaxRegionTypes+1);
for i := 0 to MaxRegionTypes do
SetLength(SDVuser[i],MaxSubRegions[i]+1, MaxSimDailyVars+1, MaxDays+1);
So in others words, the first dimension is created first and then the 2nd/3rd/4th dimensions are created next because the size of the second dimension varies.
The writing to and reading from file F (file of single) is done using BlockWrite and BlockRead commands:
for rt := 0 to MaxRegionTypes do
begin
RecordSize := (MaxSubRegions[rt]+1)*
(MaxSimDailyVars+1) *
(MaxDays+1);
BlockRead(F,SDVuser[rt,0,0,0],RecordSize);
end;
This assumes that the 2nd/3rd/4th dimensions of the SDVuser array are CONTIGUOUS in memory. Documentation and on-line comment that I can see on dynamic arrays suggests this is true.
But I sometimes get Range Check errors associated with the BlockRead which I am thinking might be caused by non-contiguity. I am also getting odd exceptions occurring elsewhere which again I think may be caused by memory being trampled because the array is not in fact contiguous.
Question 1: Does the SetLength para create a contiguous block of memory for the 3 dimensions I create in one go?
Question 2: Do the secondary SetLength operations cause the entire 4 dimensional structure to be recreated each time to ensue that the WHOLE array is contiguous - my observation is that assuming this causes lots more problems elsewhere and so I have avoided making this assumption.
Hope someone can clarify the situation
Best wishes
Jon
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi both
Thanks for your responses.
I have taken a step back and rewritten the code so that it makes NO assumptions about contiguity of a multi dimensioned dynamic array and my memory problems have gone away.
So I think in summary:
A single dimensioned dynamic array IS contiguous
An array of variable sized arrays constructed in a dynamic array will almost certainly NOT be contiguous (although elements of the individual dimensions MIGHT be).
Relying on any sort of contiguity of a multi-dimensioned dynamic array is dangerous and to be avoided.
Jon
Thanks for your responses.
I have taken a step back and rewritten the code so that it makes NO assumptions about contiguity of a multi dimensioned dynamic array and my memory problems have gone away.
So I think in summary:
A single dimensioned dynamic array IS contiguous
An array of variable sized arrays constructed in a dynamic array will almost certainly NOT be contiguous (although elements of the individual dimensions MIGHT be).
Relying on any sort of contiguity of a multi-dimensioned dynamic array is dangerous and to be avoided.
Jon
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
MerijnB
Thanks. I think my original question was not as clear as it could have been :-)
As you say I can see no reason why the second set of 3 dimensional arrays should not be contiguous, but my findings suggest that if you pass the starting address of that part of the array to the BlockWrite/BlockRead you don't always get want you think you might.
My solution has been to create a new single dimensioned array (which definitely is contiguous) and to copy (element by element) the stuff in the 3-dimensional array into that contiguous block and then to write that out, and then to reverse the process for a BlockRead. This makes the whole thing stable again.
Jon
Thanks. I think my original question was not as clear as it could have been :-)
As you say I can see no reason why the second set of 3 dimensional arrays should not be contiguous, but my findings suggest that if you pass the starting address of that part of the array to the BlockWrite/BlockRead you don't always get want you think you might.
My solution has been to create a new single dimensioned array (which definitely is contiguous) and to copy (element by element) the stuff in the 3-dimensional array into that contiguous block and then to write that out, and then to reverse the process for a BlockRead. This makes the whole thing stable again.
Jon
I'm not 100% sure, but I think that when you do a SetLength() on the first dimension, all the dynamic arrays in the second dimension will be set to 0 length (or to unknown status).
So in short:
1) no, only for the first dimension
2) yes
One note: depending on which Delphi version you are using large dynamic arrays can cause problems for the standard memory manager (memory fragmentation = memory leak while you don't actually leak memory).