Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Delphi 6 Extra Bytes in "Record" definition not in D5

Status
Not open for further replies.

sijgs

Programmer
Dec 29, 2001
100
0
0
CA
I recently had to change from Delphi 5->6 (if'n it ain't broke don't fix it, but it broke so...) I have applied all available maintenance to D6.

I have records built like:

Sub_Rec = Record
v1 : Integer;
v2 : integer;
case byte of
1: (v3 : Integer);
2: (v4 : String);
3: (v5 : String[10];
case integer of
1: (vx : byte);
2: (vy : Longint));
End;

Problem is that at each "case" under D6 there are "additional bytes" that have been added to the record. I wrote a program that calculates the offset of every variable and there are REALLY extra bytes that cannot be accounted for.

Both D5 and D6 have been set to NOT align (or to byte align) variables so there should be no offset to "next variable" based on variable type and the "map" I produce from the compiled D5 version shows no gaps in the variables.

The problem this creates is that I still use D5 programs at the same time as the ONE D6 program that had to be converted and the records come out 3 bytes different, right at the "case" points and that of course creates a "read past end of file" error.

I can supply the program if someone really loves to debug as I can't find any other entries that address this issue.

Thanks for any help
JGS
 
I've not had any problem with record size and i'm using Pascal 7, Delphi 5 and Delphi 7. I assume if you SizeOf( The typed record ) you're getting different results?

Can you post an example record type?



There are 10 types of people in the world. Those that understand binary and those that don't.
 
StellaIndigo:

Yes, sizeof(variable of type myrec) produces different results. As I posted, I even wrote a program to list the variable and it's relative offset from 0 and at each "case" there are discrepancies in the "offset" of the variables. Sometimes 1 byte, sometimes 2. And, if you look at the "map" that it produces, the discrepancies are noted by the offset being different.

As to a sample record, certainly!

Type
MyRec = Record
v1 : String[2];
V2 : String[1];
v3 : String[1];
v4 : String[2];
v5 : String[2];
v6 : String[9];
v7 : String[6];
v8 : String[20];
v9 : String[1];
Case byte of
0 :
(v10 : String[16];
v11 : String[23];
v12 : String[15];
v13 : String[22];
v14 : String[8]);

1 :

(v15 : String[16];
v16 : String[23];
v17 : String[15];
v18 : String[22];
v20 : String[8];
v21 : String[8];
v22 : String[7];
case char of
'A':(v23 : String[19];
v24 : String[19];
v25 : String[19]);
'B':(v26 : string[50]));


2 :

(v27 : String[16];
v28 : String[38];
v29 : String[1];
v30 : String[10];
v31 : String[10];
v32 : String[8];
v33 : String[16];
v34 : String[40];
v35 : String[18]);


End; { of MyRec }

Note: The names have been changed to protect the innocent.... ;-)

Regards
JGS
 
For what it's worth, I get the sizeof(MyRec) to be 224 bytes using Delphi 5 and Delphi 7. I don't have Delphi 6.

Andrew
 
OK you need to add the reserved word packed to the record definition,

Myrec = packed record

You'll find the record shrinks to the expected size.

I would also strongly recommend tagging your case statements i.e.

case mybyte : byte of

Although syntactically both are correct.

Stella

There are 10 types of people in the world. Those that understand binary and those that don't.
 
Stella:

This is unfortunate.... I see what you are saying, and read up on it and indeed that would seem to solve the problem...

However,

I happened to be sitting at another desk today, and was trying this and that to put together the "sample" you requested, etc. When I compiled them both under D5 and D6 on this machine THE PROBLEM WASN'T THERE!!!!!

So, before you had answered, I had decided to uninstall/reinstall on the "usual" (usual=guilty) machine.

I uninstalled D6 and rechecked that D5 was still working and got the proper length, then reinstalled D6 and tried it (on the "usual" machine) and it was O.K. ??

Then I put the maintenance on one step at a time, even BOOTING between steps and trying it and now the maintenance is on and the problem is GONE!

BOOOOOOOO-WEEEEEEE-OOOOOOOO!

But in any regard, thank you for the pointer to that piece of info, I had not been aware of any other setting other than the one in Project Options | Compiler | Record field alignment (D6) -or- Aligned record fields (D5) are they perhaps the same only one is global for the project and the other would leave it to a single record? If so, then what the heck was wrong with this install of D6 that is gone now??????

Thanks again
JGS
 
Just a quickie, what does a case staemant do in a record structure definition? I've never seen that before
 
A bit of safety advice: When you're writing records to disk, always specify them as packed. Saves *LOTS* of headaches!
 
KempCGDR:

It's called the "variant" section of the record. Basically, it allows you to define multiple overlays of the same area. Each "case number" like:
Case Byte of
1: ...
2: ...

starts at the same location at the end of the "common" section but you can address the variables by ANY of the names in ANY of the case statements at ANY time so one has to be careful as a variable in "overlay" 1 may be right on top of 3 variables in "overlay" 2.

The compiler makes the total record size as the size of the common area (portion on top of any "case") plus the size of the LARGEST overlay (case number).

It's a fancy way of being able to use the the data area in multiple ways... but if you start "crossing" variables like using one from case 1: then using one from case 2: that overlays the one from case 1: THEN go back and try to access the variable in case 1: ..... you get very weird results....

here's a simple example: (and it's abnormal behaviour)

Type
MyRec = record
v1 : Integer;
v2 : integer;
case byte of
1: (v3 : string[19]);
2: (v4, v5, v6 : LongInt);
End;

var
My_Var : MyRec;
Begin
With My_Var Do
Begin
v1 := 1;
v2 := 2;
v3 := 'This is a string';
//
// Note: at this point everything is o.k.
// if you reference v1, v2, and v3 everything is
// just as you have set it.
//
// NOW the gotcha!
v4 := 0;
v5 := 1;
v6 := 2;
//
// at this point if you reference v3, it's a null string
// because the longint v4 starts EXACTLY in storage where
// the length byte of v3 starts and since you set v4 to
// 0, you have essentially set the string to ''

End;
End;

To get around having this happen, one (at least one...me) should attempt to use these different "overlays" at different "times" during a program, like at formcreate use 1:, and at buttonclick use 2: since formcreate is already finished (assuming you don't need those variables anymore).

To read the Delphi version of having this explained look up variant in help...


HTH
JGS
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top