我正在阅读关于 C 语言库的文章,但是我还没有找到关于目标文件是什么的解释。其他编译文件和目标文件之间的真正区别是什么? 如果有人能用人类语言解释,我会很高兴的。
对象文件就是在编译一个(或多个)源文件时得到的。
它可以是完整的可执行文件或库,也可以是中间文件。
目标文件通常包含本机代码、链接器信息、调试符号等。
对象文件是编译阶段的实际输出。它主要是机器代码,但有信息,让链接器看到什么符号,以及它需要的符号,以便工作。(作为参考,“符号”基本上是全局对象、函数等的名称。)
链接器获取所有这些目标文件并将它们组合成一个可执行文件(假设它可以,即: 不存在任何重复或未定义的符号)。如果您不告诉编译器使用命令行选项“只编译”,那么许多编译器将为您做这件事(即: 它们自己运行链接器)。(-c是一个常见的“只编译; 不链接”选项。)
-c
对象文件就是编译后的文件本身。两者之间没有区别。
可执行文件是通过链接 Object 文件形成的。
对象文件包含 CPU 可以理解的低级指令。这就是为什么它也被称为机器代码。
这个低级机器代码是指令的二进制表示,你也可以直接使用汇编语言编写,然后使用汇编程序将汇编语言代码(用英语表示)处理成机器语言(用十六进制表示)。
下面是用高级语言(如 C)编写的这个过程的一个典型的高级流程
经过预处理
给出优化的代码,仍然在 C 中
经过编译器
- > 给出汇编代码
通过一个组装程序
以机器语言给出存储在 OBJECT 文件中的代码
通过连接器
- > 获取可执行文件。
这个流程可能有一些变化,例如大多数编译器可以直接生成机器语言代码,而不需要经过汇编程序。类似地,他们可以为您进行预处理。尽管如此,为了更好地理解,分解这些组成部分还是很不错的。
对象文件是依赖于函数、符号和文本来运行程序的代码。就像旧的电传机一样,需要用电传打字机向其他电传机发送信号。
同样,处理器需要二进制代码才能运行,目标文件就像二进制代码一样,但是没有链接。链接会创建额外的文件,这样用户就不必自己编译 C 语言了。用户可以直接打开 exe 文件一旦目标文件链接到一些编译器,如 c 语言,或 vb 等。
有三种目标文件。
以链接时可与其他可重定位对象文件组合的形式包含机器代码,以便形成可执行对象文件。
如果您有一个 a.c源文件,要使用 GCC 创建它的目标文件,您应该运行: gcc a.c -c
a.c
gcc a.c -c
整个过程将是: 预处理器(cpp)将在 a.c. 上运行,它的输出(仍然是源代码)将提供给编译器(cc1)。它的输出(汇编)将提供给汇编程序,汇编程序将生成 relocatable object file。该文件包含目标代码和链接(如果使用了 -g则进行调试)元数据,并且不能直接执行。
relocatable object file
-g
可以在加载时或运行时动态加载的可重定位对象文件的特殊类型。共享库就是这类对象的一个例子。
包含可以直接加载到内存中(通过加载程序,例如 执行官)并随后执行的机器代码。
在多个 relocatable object files上运行链接器的结果是 executable object file。链接器通过将所有相同类型的输入部分(例如 .data)合并到相同类型的输出部分,从左到右合并命令行中的所有输入对象文件。它使用 symbol resolution和 relocation。
relocatable object files
executable object file
.data
symbol resolution
relocation
当对 static library进行链接时,输入对象中引用的函数将被复制到最终的可执行文件。 使用 dynamic libraries,会创建一个符号表,它将启用与库的函数/全局变量的动态链接。因此,结果是一个部分可执行的对象文件,因为它依赖于库。如果库不存在,则该文件不能再执行)。
static library
dynamic libraries
联系过程可以如下进行: ld a.o -o myexecutable
ld a.o -o myexecutable
命令: gcc a.c -o myexecutable将调用点1和点3(cpp-> cc1-> as-> ld1)上提到的所有命令
gcc a.c -o myexecutable
实际上是 Collect2,它是 ld 的包装器。