Well, the first problem is that you stored a non-packed record to disk. Field and array packing is allowed to change between product releases because normally the layout in memory is not visible outside of the process. You've broken that rule.
If the byte padding defaults changed between Delphi 7 and Delphi 2009, find out what the defaults were in D7 and set the defaults to the same in Delphi 2009. Also check the array packing default. I can't remember if there is a separate setting for this.
Take a look at your record structure in Delphi 2009 in the debug memory view. Some or all of the additional size may be due to padding of the record itself (not the fields within it) so that when the record is used in an array the array elements are on speedy machine boundaries. If none of this helps, create a temporary packed record type in D2009 and manually insert byte padding fields between the actual data fields until the record size and field alignments match the D7 layout.It's not just size, it's field alignments.
Read your old data file in using this temp packed record. Then transfer the data field by field into your "real" record type in D2009 and write out a new file. And while you're at it, pack that record type in D2009 so this doesn't happen again.
4 This is all assuming you don't have the option to go back to D7 and modify the code there to pack the record structure and write out a file of packed records. That would be less work than manually trying to match the byte padding after the fact. – dthorpe Jul 8 '10 at 18:06 nd sight is always 20/20... and forward thinking development (and developers) does not always happen.
Good idea about the packed record with spaces for 2009/2010. We'll give that a try. – Jason Nethercott Jul 8 '10 at 18:16 6 ndsight should be educational, too.
Writing unpacked records to a file should happen only once per career. ;> – dthorpe Jul 8 '10 at 19:05 1 This doesn't really answer the question. The question asked why record-layout rules that changed between the two Delphi versions affected the first record but not the second.
This answer gives suggestions on how to solve the problem resulting from those changes, but that's not what the question asked for. What is it about TToTry that makes it susceptible to different alignment rules whereas TMyRecord appears immune? – Rob Kennedy Jul 8 '10 at 20:50 5 I can't answer policy questions of why the product dev team decided to make this change or that.As for why the TMyRecord size is stable between releases, has anyone checked the project file to see if alignment is set explicitly?
TMyRecord is also a very different structure from TToTry. TToTry is dominated by 8 10-byte Extended fields and 12 arrays of 3 10 byte Extended fields. TMyRecord throws in integers and bytes and a lot fewer 10 byte extendeds.
There's a lot less in TMyRecord that might need padding for N-word alignment. – dthorpe Jul 8 '10 at 21:39.
I believe you've hit a feature!. I could not get a reasonable size with your TToTry with D2007 so I had to look up field addresses with the debugger; First, size of the below record, {$A8} type TToTry = record j: array1..3 of Extended; k: array1..3 of Extended; l: array1..3 of Extended; m: array1..3 of Extended; end; is 128 (32*4). This is expected, since an Extended is 10 bytes, 30 bytes would align on 32 bytes.
But size of this record, {$A8} type TToTry = record j, k, l, m: array1..3 of Extended; end; is 120 (30*4). This is certainly unexpected - fields should still align on an 8 byte boundary. (I don't have D7 to verify but my thinking is that:) So now we know that grouped fields are packed, it follows that the alignment on D7 is 8 bytes and your record is nearly packed; TToTry = Record a,b,c,d : Extended; // 40 bytes (8*5) e,f,g,h : Extended; // 40 bytes (8*5) I : String15; // 16 bytes (8*2) j,k,l,m,n,o,p,q,r,s,t: Array1..3 of Extended; // 330 bytes End; The compiler is padding 6 bytes to the last group to have it a multiple of 8 and then you get 40+40+16+336 = 432 bytes.
With D2009/D2010 you are either declaring each field - without grouping them, or the behavior is changed. Either way pack your record and add a 6 byte array dummy field to the end, and you should be good to go. If that does not work, look at the field addresses of your record with D7, then create an exact duplicate on D2009 by using a packed record and using dummy fields as necessary, after you've imported your stored data you can drop the dummy fields.
-- I've never known such behavior and I can't find it documented anywhere. Still, it is so much like a feature that I'm hesitant to call it a bug. I don't know the behavior is the same with D2009 or D2010, test to see if it is.
If it is, to get expected results - not to have half-packed records - don't be lazy and declare each and every field on its own for non-packed records.
The size of the second record in Delphi 2009 is 128 bytes – Serg Jul 9 '10 at 1:59 @Serg - thanks for looking it up, so it's not a feature. In fact I encountered other strange/unexpected alignments while testing with D2007. I'm glad that later versions have it straight!
– Sertac Akyuz Jul 9 '10 at 2:20.
Applying {$A8} directive does not mean that all record fields are aligned at 8-byte boundary - the compliler uses a different alignment strategy. For example, the size of {$A8} type TToTry = record a: byte; b: word; c: longword; end; is 8 bytes in Delphi 2009, because the compiler aligns 2-byte value at 2-byte boundary, 4-byte value at 4-byte boundary, and the only actual alignment in the above example is be field aligned at 2-byte boundary. As for the original question what changed between Delphi 7 and Delphi 2009 - read Sertac Akyuz answer and my comment to it.
Ah, Ok! That's what I meant by 'strange/unexpected' with my comment to your comment on my answer. But is this to be expected?
The docs say: "In the {$A8} or {$A+} state, fields in record types that are declared without the packed modifier and fields in class structures are aligned on quad word boundaries. " – Sertac Akyuz Jul 9 '10 at 2:32 1 @Sertac: Quad word alignment only applies to data types that are at least 8 bytes in length. There's little to be gained on x86 architecture by putting a byte field on an 8 byte boundary.(It could help with cache line collisions in the L2 cache, but that's really really minor).
As Serg said, data types align to their natural boundary (= size of data) up to the $A/n/ size. Note that there are multiple alignment points to consider: offset of fields from the start of the struct, alignment of data within the arrays, and padding of the record itself to align well when it is used in an array. – dthorpe Jul 9 '10 at 16:47 1 @dthorpe - Thanks, all make sense.
But I wish the 'structured types' or the 'align fields' topic in the documentation be more explicit on this, especially for those like me who have no knowledge of the underlying architecture.. – Sertac Akyuz Jul 9 '10 at 19:07.
I believe the default alignment was made wider. Specify alignment 4 in the later versions and see if it comes out the way you want. For the future you should make sure that any record that is going to be written out to disk is stored packed so you don't get burned this way.
Edit: Since none of the alignments work (which surprises me) I would go back to the original and figure out how it really is aligned. Fill the record with something like $FF, put the data in and write it out--see where the $FFs survived. Take the new record, make it packed and add fillers to match the padding in the old record.
One thing: Is this actually just one record? In the old days I have used objects as fake records with inheritance--oops, at the point of the inheritance the normal alignment was applied and I couldn't stop it. I ended up having to pad before the data in order to make the forced alignment not break my data.(This was going to an API, it HAD to be right, I couldn't process the fields independently.).
– Jason Nethercott Jul 8 '10 at 18:05 Found it: {$A4}. But it didn't help. The number is now 464.
I tried all the other {$A? } possibilities and none match. – Jason Nethercott Jul 8 '10 at 18:12.
Well, the first problem is that you stored a non-packed record to disk. Field and array packing is allowed to change between product releases because normally the layout in memory is not visible outside of the process. You've broken that rule.
I believe you've hit a feature!. I could not get a reasonable size with your TToTry with D2007 so I had to look up field addresses with the debugger.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.