c - c语言中链接和加载有什么区别

标签 c compilation

动态库的链接和加载是否都在运行时发生? 还是仅在运行时加载库?

最佳答案

请参阅前面关于静态链接和动态链接之间的区别的非常好的观点。假设您指的是动态链接,那么:

加载和(动态)链接都是由链接器完成的——在 linux 和其他类似 Unix 的系统上,这是由 /lib/ld.so 完成的,这是由几乎所有情况下的操作系统。 ld.so 依次加载您的应用程序 - mygameBinary 到内存中,然后 ld.so 从文件中读取mygameBinary 它需要的动态链接库列表。

链接器 ld.so 然后依次将这些库中的每一个加载到内存中,例如libc.solibpthread.solibopengl.so,并查看这些可能需要的其他库,例如libm.so.

加载 完成后,链接 开始,这是一个查看命名对象或函数的过程,导出 由一个库或应用程序,并由另一个库或应用程序导入。然后链接器更改各种引用,有时还更改代码以更新每个库中未链接的数据指针和函数调用,以指向实际数据或函数所在的位置。例如,在 mygameBinary 中对 printf 的调用一开始没有指向任何内容(实际上它只是调用了链接器),但在链接之后变成了到 printf< 的跳转 libc 中的函数。

此链接完成后,通过调用 mygameBinary 中的 _start 函数启动应用程序,然后调用 main,您的游戏开始。

这种方式的动态链接对于支持以下内容是必要的:

  • 应用程序发布后库更新,这会改变函数和数据的位置。
  • 在不同版本的操作系统上运行的单个应用程序
  • 不确定库或应用程序在内存中的加载位置
  • 通过在多个应用程序之间共享库使用的物理内存来减小核心的大小。

一些操作系统在细节上有所不同,例如 OSX 和 AIX 都将一组特定的库预加载到内存中的固定位置。这意味着它们不需要加载,只需链接,这可能会更快。

某些操作系统(例如 OSX,有时是 Linux)支持预链接,这是一个脚本在您启动应用程序之前运行系统上的应用程序并进行链接的过程。当您启动它们时,您就不需要链接它们。这很重要,因为在您启动应用程序时链接会占用您计算机的大量时间,并且某些应用程序可能每秒启动多次,例如 gcccppas 在应用程序构建过程中,或在索引计算机数据时过滤脚本 (OSX Spotlight)。

关于c - c语言中链接和加载有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1951498/

相关文章:

核心转储到 char ** 指针上

c - C 中的头文件和源文件如何工作?

c - #定义带逗号的表达式

c - For 循环未按预期工作

C++ 错误 : "' class' does not name a type"and "invalid use of incomplete type ‘struct ...' "

c++ - NVCC,与 -Xcompiler 的奇怪交互

gradle - 使用Gradle编译JasperReports会得到不受支持的版本错误

Java编译错误:

C线程调度(和asm)

c - 简单代码 : "declared argument argc is missing" 上的 A/UX cc 编译器错误