6

在查看我们遗留的 Delphi 7 程序中的一些代码时,我注意到到处都有记录标记为packed. 这当然意味着记录是逐字节存储的,并且没有对齐以便 CPU 更快地访问。打包似乎是盲目地试图超越编译器或其他东西 - 基本上是重视几个字节的内存而不是更快的访问

示例记录:

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

我应该解决这个问题并使每条记录正常还是“不”打包?或者对于现代 CPU 和内存,这可以忽略不计并且可能是浪费时间?是否有任何因拆包而导致的问题?

4

4 回答 4

23

如果不完全了解每个打包记录是如何在应用程序代码中使用的,就无法回答这个问题。这与询问“我应该将此变量声明从 Int64 更改为 Byte 吗?”相同。

在不知道该变量将被期望并需要什么值来维持答案的情况下,答案可能是肯定的。或者它可能不是。

在你的情况下也是如此。如果需要打包记录,则应将其打包。如果不需要打包,那么不打包也没有坏处。如果您不确定或无法分辨,那么最安全的做法是让它们保持原样。

作为做出此决定的指南(如果您决定继续),需要或建议打包记录的情况包括:

  • 记录值的持久性
  • 与 [可能] 不同编译的代码共享记录值
  • 与外部定义的结构严格兼容
  • 故意将类型布局覆盖在不同结构的内存上

这不一定是一份详尽的清单,这些清单的共同点是:

  • 由相邻字节中的一系列值组成的记录,任何潜在的记录生产者或消费者都必须并且可以依赖这些值,而不会受到编译器或其他因素的干扰

我的建议是(如果可能且可行)您确定包装在每种情况下的用途,并将相关文档添加到记录声明本身,以便将来有相同问题的任何人都不必经历那个发现过程,例如:

  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

如果记录被存储/检索为打包或以任何方式传输到期望它被打包的接收器,则不要更改它。

更新 :

您的示例中声明了一个字符串类型。看起来很可疑,因为将记录存储在二进制文件中不会保留字符串内容。

于 2011-10-11T22:22:08.870 回答
0
  • 打包记录的长度与成员的大小完全相同。
  • 没有优化打包记录(它们对齐 -> 因此更高)以获得更好的性能。
于 2017-04-18T09:38:57.180 回答