20

什么是 .Delphi DCU 文件?

我相信它代表“Delphi Compiled Unit”。我是否正确假设它包含目标代码,因此对应于从 C/C++ 源代码文件编译的“.o”文件?

4

3 回答 3

32

我相信 .dcu 通常表示“Delphi 编译单元”,而不是 .pas 文件,它只是“Pascal 源代码”。

.dcu 文件是 DCC 编译器在编译 .pas 文件后生成的文件(.dfm 文件被转换为二进制资源,然后由链接器直接处理)。

它类似于其他编译器生成的.o.obj文件,但包含有关符号的更多信息(因此您可以从中对单元的接口部分进行反向工程,省略注释和编译器指令)。

.dcu 文件在技术上不是“缓存”文件,尽管如果您不删除它们并且何时不需要重新编译它们,您的构建将运行得更快。.dcu 文件与生成它的编译器版本相关联。从这个意义上说,它的可移植性不如 .o 或 .obj 文件(尽管它们也存在兼容性问题)

这是一些历史记录,以防它添加任何内容。

编译器传统上将源代码语言翻译成某种中间形式。解释器不这样做——他们只是直接解释语言并立即运行应用程序。BASIC 是解释语言的经典例子。DOS 和 Windows 中的“命令行”具有一种可以写入名为“批处理文件”且扩展名为 .bat 的文件的语言。但是在命令行上输入内容会直接执行它们。在 *nix 环境中,有许多不同的命令行解释器 ( CLI ) 例如shcshbashksh. 您可以从所有这些文件中创建批处理文件——这通常被称为“脚本语言”。但是现在有很多其他语言既可以解释又可以编译。

无论如何,例如,Java.Net编译成一种称为中间“字节码”表示的东西。

Pascal最初是作为单通道编译器编写的,而Turbo Pascal(源自 PolyPascal)——具有CP/MCP/M-86DOS的不同版本——直接生成一个二进制可执行文件(COM)文件,该文件在那些运行系统。

Pascal 最初被设计为一种小型、高效的语言,旨在鼓励使用结构化编程和数据结构化的良好编程实践;Turbo Pascal 1最初被设计为一个内置非常快速的编译器的IDE ,并且是 DOS 和 CP/M 市场上一个可负担得起的竞争对手,可对抗当时冗长的编辑/编译/链接周期。Turbo Pascal 和 Pascal 与当时的任何编程环境都有类似的限制:内存和磁盘空间以千字节为单位,处理器速度以兆赫兹为单位。

链接到可执行二进制文件会阻止您链接到单独编译的单元和库。

在 Turbo Pascal 之前,有UCSD p-System操作系统(支持多种语言,包括 Pascal。当时的 UCSD Pascal 编译器已经用单位扩展了 Pascal 语言)编译成伪机器字节码(称为 p-code)允许将多个单元链接在一起的格式。虽然很慢,

同时,c在VAXUnix环境中演变,并编译为 .o 文件,这意味着“目标代码”而不是“源代码”。注意:这与我们今天所说的“对象”完全无关。

Turbo Pascal 到并包括版本 3 直接生成的 .com 二进制输出文件(尽管您可以使用修改那些覆盖文件),并且从版本 4 开始支持将代码分离为首先编译成 .tpu 文件然后链接到最终可执行二进制文件的单元. Turbo C 编译器生成 .obj(目标代码)文件而不是字节码,Delphi 2 引入了 .obj 文件生成,以便与 C++ Builder 合作。

目标文件在每个单元内使用相对寻址,并且稍后需要所谓的“修复”(或重定位)以使它们运行。修正指向预期存在于其他目标文件或库中的符号标签。

有两种“修复”:一种是由称为“链接器”的工具静态完成的。链接器获取一堆目标文件并将它们缝合在一起,形成类似于拼布被子的东西。然后它通过插入指向所有外部定义标签的指针来“修复”所有相对引用。

第二次修复是在程序加载运行时动态完成的。它们是由一种叫做“加载器”的东西完成的,但你永远看不到。当您在命令行上键入命令时,将调用加载程序将 EXE 文件加载到内存中,根据文件加载位置修复剩余链接,然后将控制权转移到应用程序的入口点。

所以当 Borland 在 Turbo Pascal 中引入单位时,.dcu 文件起源于 .tpu 文件,然后随着 Delphi 的引入而改变了扩展名。它们与 .obj 文件非常不同,尽管您可以从 Turbo Pascal 和 Delphi 链接到 .obj 文件。

Delphi 还完全隐藏了链接器,因此您只需编译和运行即可。但是,所有链接器设置仍然存在,在 Delphi 的选项窗格之一中。

于 2014-07-10T01:31:24.680 回答
7

除了 David Schwartz 的回答之外,还有一种情况是 dcu 实际上与用其他语言生成的典型 obj 文件完全不同:通用类型定义。如果在 Delphi 单元中定义了泛型类型,编译器会将此代码编译为语法树表示而不是机器代码。然后将该语法树表示存储在 dcu 文件中。当泛型类型随后在另一个单元中使用和实例化时,编译器将使用此表示并将其与使用泛型类型的单元的语法树“合并”。你可以认为这有点类似于方法内联。顺便说一句,这也是为什么大量使用泛型的单元需要更长的编译时间的原因,尽管泛型类型是从 dcu 文件“链接”的。

于 2014-07-10T09:15:57.380 回答
1

Delphi 编译单元包含目标代码和预编译头文件,因此在某种程度上与 obj 文件和 .pch / .gch 文件相当。

Delphi 源文件的“接口”部分对应于头文件,“实现”部分创建目标代码。

预编译的头文件可以显着减少编译和链接时间。DCU 标头部分提供到其他引用单元的链接信息,不必重新发现。

在 Delphi / Turbo Pascal 环境中,预编译的头文件支持严格的类型检查,如果使用了像 .coff 或 .obj 这样的对象文件格式,则需要源代码引用。(在 C++ 中,名称修饰提供了类似但不太完整的功能)。

于 2017-05-25T06:35:11.847 回答