Главная страница | назад





Article #23008: Variable alignment problems in record type.

Question:

Why am I getting garbage returned from my record variables?

Answer:

This is most likely a problem with field alignment. If you are using an application in Delphi 5 that was migrated from an earlier version you should know that alignment changed in Delphi 5. See Delphi 5 help under Contents | Upgrading to Delphi 5 | Compatibility issues | Default alignment.

If this is not your issue there is also a bug in Delphi 5 you should be aware of. If no compiler directive is specified the default is {$ALIGN ON} or simply {$A+}. Aligned means the record is unpacked and each field takes a fixed amount of space in memory based on the datatype. Packing is done to save memory.

The bug in Delphi can cause packing or inconsistent alignment to occur even when alignment is on, {$A+}. It occurs when multiple record fields are declared in the same line. Moreover, this alignment is not consistent, varying between 2, 4 and 6.

The solution is easy; declare each field in a new line. Here's an example that demonstrates the issue with Extended types. Since they are all Extended types they should all use the same amount of space in memory. Therefore the difference between each of the memory addresses should all be the same, but notice they are not. We've only observed this behavior with Extended and Real48 types. We've heard reports of it happening with other data types but have not been able to reproduce it.

procedure TForm1.Button1Click(Sender: TObject);
var
  test1 : record
            field1, field2 : Extended;    // Packed
            field3 : Extended;            // Not packed
            field4 : Extended;            // Not packed
          end;
begin
showmessage('Address of field1: ' + Inttostr(longint(@test1.field1)) + #10#13
          + 'Address of field2: ' + IntTostr(longint(@test1.field2)) + #10#13
          + 'Address of field3: ' + Inttostr(longint(@test1.field3)) + #10#13
          + 'Address of field4: ' + IntTostr(longint(@test1.field4)));
end;

Last Modified: 11-OCT-00