6

While reviewing some code in our legacy Delphi 7 program, I noticed that everywhere there is a record it is marked with packed. This of course means that the record is stored byte-for-byte and not aligned to be faster for the CPU to access. The packing seems to have been done blindly as an attempt to outsmart the compiler or something -- basically valuing a few bytes of memory instead of faster access

An example record:

TFooTypeRec = packed record
    RID                 : Integer;
    Description         : String;
    CalcInTotalIncome   : Boolean;
    RequireAddress      : Boolean;
end;

Should I fix this and make every record normal or "not" packed? Or with modern CPUs and memory is this negligible and probably a waste of time? Are there any problems that can result from unpacking?

4

4 に答える 4

23

There is no way to answer this question without a full understanding of how each of those packed records are used in your application code. It is the same as asking "Should I change this variable declaration from Int64 to Byte ?"

Without knowing what values that variable will be expected and required to maintain the answer could be yes. Or it could be no.

Similarly in your case. If a record needs to be packed then it should be left packed. If it does not need to be packed then there is no harm in not packing it. If you are not sure or cannot tell, then the safest course is to leave them as they are.

As a guide to making this determination (should you decide to proceed), situations where record packing is required or recommended include:

  • persistence of record values
  • sharing of record values with [potentially] differently compiled code
  • strict compatibility with externally defined structures
  • deliberately overlaying a type layout over differently structured memory

This isn't necessarily an exhaustive list, and what these all have in common is:

  • records comprising a series of values in adjacent bytes that must and can be relied upon by any potential producer or consumer of the record without possibility of interference from the compiler or other factors

What I would recommend is that (if possible and practical) you determine what purpose packing serves in each case and add documentation to that effect to the record declaration itself so that anyone in the future with the same question doesn't have to go through that discovery process, e.g.:

  type
    TSomeRecordType = packed record
      // This record must be packed as it is used for persistence
      ..
    end;

    TSomeExternType = packed record
      // This record must be packed as it is required to be compatible
      //  in memory with an externally defined struct (ref: extern code docs)
      ..
    end;
于 2011-10-11T23:17:33.743 に答える
8

パックされたレコードを使用する主なアイデアは、数バイトのメモリを節約することではありません。代わりに、変数がメモリ内にあると予想される場所にあることを保証することです。このような保証がなければ、ヒープ上でメモリを手動で管理し、ファイルへの書き込みとファイルの読み取りを行うことは不可能です(または少なくとも困難です)。

したがって、レコードを「解凍」すると、プログラムが誤動作する可能性があります。

于 2011-10-11T22:20:12.397 に答える
2

If the record is stored/retrieved as packed or transfered in any way to a receiver that expects it to be packed, then do not change it.

Update :

There is a string type declared in your example. It looks suspicious, since storing the record in a binary file will not preserve the string content.

于 2011-10-11T22:22:08.870 に答える
0
  • Packed record have length exactly size like members are.
  • No packed record are optimised (thay are aligned -> consequently higher) for better performance.
于 2017-04-18T09:38:57.180 に答える