Size of records in Delphi 4 and 5

I have a problem with a recordsize after installing delphi 5.0 !!

I have a record made with delphi 4, I've saved some records to file.
If I add the size of the individual elements in the record I get 2322 bytes.

In delphi 4.0 sizeof(record) = 2332 bytes.
In delphi 5.0 sizeof(record) = 2336 bytes.

Delphi 5 seems to take up 4 bytes more record-Header space than Delphi 4 ??  is that correct ??

Which means that I can't read the records back correctly with Delphi 5.0
JebAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
schutnikConnect With a Mentor Commented:
I don't know how you ever counted 2322 as you mentioned above.  The actual size (in any compiler) if your Integer size is 4 bytes and your TDateTime (defined as double) is 8 bytes is actually 2326. (with no extra space between fields)

If you turn off alignment (packed keyword or {$A-}) you get a size of 2326 with the individual field offsets and lengths as listed below.

If you turn on alignment (no packed keyword and {$A+} -- default) you get a size of 2336 with the individual field offsets and lengths as listed below.

I tested this by writing a program in D5 and testing it in D4 as well.

Here are the results from D5...

{A+}
DMI_Nr     : 0, 26
NoteNr     : 28,4
Overskrift : 32,51
Firma      : 83,130
Dato       : 216,8
init       : 224,6
Password   : 230,7
SogFelt1   : 237,31
SogFelt2   : 268,31
SogFelt3   : 299,31
Note       : 330,2001
Total      : 2336

{A-} (or packed record)
DMI_Nr     : 0, 26
NoteNr     : 26,4
Overskrift : 30,51
Firma      : 81,130
Dato       : 211,8
init       : 219,6
Password   : 225,7
SogFelt1   : 232,31
SogFelt2   : 263,31
SogFelt3   : 294,31
Note       : 325,2001
Total      : 2326


Here are the results from D4...

{A+}
DMI_Nr     : 0, 26
NoteNr     : 28,4
Overskrift : 32,51
Firma      : 83,130
Dato       : 216,8
init       : 224,6
Password   : 230,7
SogFelt1   : 237,31
SogFelt2   : 268,31
SogFelt3   : 299,31
Note       : 330,2001
Total      : 2332

{A-} (or packed record)
DMI_Nr     : 0, 26
NoteNr     : 26,4
Overskrift : 30,51
Firma      : 81,130
Dato       : 211,8
init       : 219,6
Password   : 225,7
SogFelt1   : 232,31
SogFelt2   : 263,31
SogFelt3   : 294,31
Note       : 325,2001
Total      : 2326

----------------------

The reason you see a difference in the two results with alignment is that D4 does it according to the Object Pascal documentation (help file under Mem. Mgmt) and D5 doesn't.  D5 uses 4 byte alignments for doubles, but then calculates the size of the structure as if the alignment was 8 (if it includes a double).  (The correct alignment for doubles is on the DWORD boundary (4) not the QWORD boundary (8), therefore D5 is wrong in this case -- unless of course the compiler writers meant to do this for some other reason and just didn't tell the documentation guys)

The moral of the story here is, if you want to guarantee that your structures will be laid out properly across different versions of the compiler (and even different languages), you should always use a packing of 1 (i.e. packed records).

Kelly
0
 
PeterLarsenCommented:
Listening
0
 
MotazCommented:
What is your fields in this record, please paste the list here.

Motaz
0
Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

 
JebAuthor Commented:
Const
  NoteSize = 2000;
  Max_Rec_In_StringGrid = 100;

type
  NoteRecPtr = ^NoteRec;
  CharArray  =  Array[0..NoteSize] of char;
  DMIString  =  string[25];

  NoteRec = Record
    DMI_Nr  : DMIString;
    NoteNr  : integer;
    Overskrift:string[50];
    Firma   : string[129];
    Dato    : TDateTime;
    init    : string[5];
    Password: string[6];
    SogFelt1: string[30];
    SogFelt2: string[30];
    SogFelt3: string[30];
    Note    : CharArray;
  end;
0
 
MotazCommented:
Try to decrease NoteSize four bytes (1996 instead of 2000) then test it again.
0
 
JebAuthor Commented:
I've tried that but it seems that !!  seemed reasonable but everything between a notesize of 1995 and 1999 gives a total recordsize of 2328 bytes ??
0
 
LischkeCommented:
Maybe it has to do with record packing (enabled in your D4 environment, disabled in D5 or vice versa). Just declare your record as

NoteRec = packed record
    DMI_Nr  : DMIString;
    NoteNr  : integer;
    Overskrift:string[50];
    Firma   : string[129];
    Dato    : TDateTime;
    init    : string[5];
    Password: string[6];
    SogFelt1: string[30];
    SogFelt2: string[30];
    SogFelt3: string[30];
    Note    : CharArray;
  end;

This will ensure that all data fields are packed tightly together without using fill bytes to align member at a 32bit boundary.

Ciao, Mike
0
 
kretzschmarCommented:
hi jeb,

there are two possibilities

1. Recordalignment
2. d5 stores floats(doubles) in a another way, (if i had it right in mind, in d5 are it 12 Bytes, in d4 are 8 Bytes) -> TDateTime is a Float(Double)

recordpacking will not apply the "expanded"-float

meikl
0
 
EpsylonCommented:
I did some testing and I found out that the record size is aligned to the number of bytes of the largest type used in the record.
In this case TDateTime (of type Double) take up 8 bytes. That means that the actual size of the record (retured by sizeof()) will dividable to 8.

The reason for this is probably to be compatile with M$ stuff...

The offsets of the record fields are the same in Delphi 4 and 5.
0
 
JebAuthor Commented:
It seam reasonable the a Double is 12 bytes i D5 and 8 butes in D4 which explains the 4 extra bytes in my record above !!

If i Pack the record it takes up 2326 bytes !!
0
 
kretzschmarCommented:
hi jeb,

i guess eps is more right,
because in d5
this record

type TARec = Record
             d1 : Double;
             d2 : Double;
           end;

has a size of 16. (packed 16)
this change

type TARec = Record
             d1 : Double;
             d2 : Double;
             C  : Char;
           end;
has a size of 24. (packed 17)

therefore forget my comment
about the 12 byte double

meikl
0
 
JebAuthor Commented:
if it's not the 12 bytes Double what is it then ??
0
 
EpsylonCommented:
What a difficult thing reading is.....

The largest type used in the record is TDateTime with a size of 8 bytes. In D5 this means the total size of the record must be dividable to 8.
Since 2332 is not dividable to 8, sizeof returns 2336.
0
 
JebAuthor Commented:
You wrote that once and it's ok but howcome doesn't that count for D4 too ??

0
 
kifahCommented:
Hi,
Try SmallInt instead of Integer.......
0
 
schutnikCommented:
Sorry, my answer was slightly incorrect.

D4 & D5 both use 8 byte alignment for doubles (which contradicts the documentation altogether -- 'Real types 2 for Real48 and Extended, 4 for all other real types') therefore, if we assume that the documentation is as correct as it can be, then the text 'Finally, the compiler rounds the total size of the record upward to the byte boundary specified by the largest alignment of any of the fields.' should imply that the size of the structure should be a multiple of 8 (and therefore D4 is incorrect).

Sorry for the misleading first look.
Kelly
0
 
schutnikCommented:
Ok, lets try this once again!

Sorry again for a slightly incorrect answer, so here is the correction:

D4 aligns Double on DWORD boundaries, D5 aligns them on QWORD boundaries.

Which is correct?  Well, according to the docs (in both versions, the docs are exactly -- word for word -- the same) and say that the real types should be aligned on 4 byte (DWORD) boundaries.

D4 matches the docs, D5 doesn't.

Come on guys, please update the docs, some of us actually read them! :-)

Kelly
0
All Courses

From novice to tech pro — start learning today.