链接器是做什么的?

新手上路,请多包涵

我一直想知道。我知道编译器会将您编写的代码转换为二进制文件,但链接器是做什么的?他们对我来说一直是个谜。

我大致了解什么是“链接”。这是对库和框架的引用被添加到二进制文件中的时候。我不明白除此之外的任何事情。对我来说,它“有效”。我也了解动态链接的基础知识,但没有太深。

有人可以解释这些条款吗?

原文由 Kristina Brooks 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 622
2 个回答

要了解链接器,首先要了解当您将源文件(例如 C 或 C++ 文件)转换为可执行文件(可执行文件是可以在您的机器上执行的文件或其他人的机器运行相同的机器架构)。

在后台,当程序被编译时,编译器将源文件转换为目标字节码。此字节码(有时称为目标码)是只有您的计算机体系结构才能理解的助记指令。传统上,这些文件具有 .OBJ 扩展名。

创建目标文件后,链接器开始发挥作用。通常,一个真正的程序做任何有用的事情都需要引用其他文件。例如,在 C 语言中,将您的姓名打印到屏幕上的简单程序将包括:

 printf("Hello Kristina!\n");

当编译器将你的程序编译成 obj 文件时,它只是简单地引用了 printf 函数。链接器解析此引用。大多数编程语言都有一个标准的例程库来涵盖该语言所期望的基本内容。链接器将您的 OBJ 文件与此标准库链接。链接器还可以将您的 OBJ 文件与其他 OBJ 文件链接。您可以创建具有可由另一个 OBJ 文件调用的功能的其他 OBJ 文件。链接器的工作方式几乎类似于文字处理器的复制和粘贴。它“复制”出程序引用的所有必要函数并创建一个可执行文件。有时,复制出来的其他库依赖于其他 OBJ 或库文件。有时,链接器必须非常递归才能完成其工作。

请注意,并非所有操作系统都创建单个可执行文件。例如,Windows 使用 DLL 将所有这些功能放在一个文件中。这会减小可执行文件的大小,但会使可执行文件依赖于这些特定的 DLL。 DOS 曾经使用称为覆盖(.OVL 文件)的东西。这有很多目的,但一个是将常用的功能放在一个文件中(如果您想知道,它的另一个目的是能够将大型程序放入内存中。DOS 在内存方面存在限制,并且覆盖可以从内存中“卸载”,其他覆盖可以“加载”在该内存之上,因此名称为“覆盖”)。 Linux 有共享库,这与 DLL 基本相同(我认识的 Linux 硬核人士会告诉我有很多很大的不同)。

希望这可以帮助您理解!

原文由 Icemanind 发布,翻译遵循 CC BY-SA 3.0 许可协议

当编译器生成一个目标文件时,它包括在该目标文件中定义的符号条目,以及对该目标文件中未定义的符号的引用。链接器获取这些并将它们放在一起,因此(当一切正常时)来自每个文件的所有外部引用都由其他目标文件中定义的符号来满足。

然后,它将所有这些目标文件组合在一起,并为每个符号分配地址,并且在一个目标文件具有对另一个目标文件的外部引用的情况下,它会填充每个符号的地址,无论它被另一个对象使用。在典型情况下,它还会构建一个使用的任何绝对地址的表,因此加载器可以/将在加载文件时“修复”地址(即,它将基本加载地址添加到每个地址,所以它们都引用正确的内存地址)。

相当多的现代链接器还可以执行一些(在少数情况下 _很多_)其他“东西”,例如以只有在所有模块可见时才有可能的方式优化代码(例如,删除包含的函数因为其他模块 可能 会调用它们,但是一旦将所有模块放在一起,很明显没有任何东西会调用它们)。

原文由 Jerry Coffin 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题