我经常听到术语“静态链接”和“动态链接”,通常是指用 C 、 C++ 或 C# 编写的代码。它们是什么,它们到底在说什么,它们在连接什么?
原文由 UnkwnTech 发布,翻译遵循 CC BY-SA 4.0 许可协议
我经常听到术语“静态链接”和“动态链接”,通常是指用 C 、 C++ 或 C# 编写的代码。它们是什么,它们到底在说什么,它们在连接什么?
原文由 UnkwnTech 发布,翻译遵循 CC BY-SA 4.0 许可协议
因为上述帖子都没有 真正展示如何 静态链接某些东西并看到你做对了,所以我将解决这个问题:
一个简单的C程序
#include <stdio.h>
int main(void)
{
printf("This is a string\n");
return 0;
}
动态链接C程序
gcc simpleprog.c -o simpleprog
并在二进制文件上运行 file
:
file simpleprog
这将表明它是动态链接的,如下所示:
simpleprog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xf715572611a8b04f686809d90d1c0d75c6028f0f, not stripped
这次让我们静态链接程序:
gcc simpleprog.c -static -o simpleprog
在这个静态链接的二进制文件上运行文件将显示:
file simpleprog
现在结果将是
simpleprog: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.26, BuildID[sha1]=0x8c0b12250801c5a7c7434647b7dc65a644d6132b, not stripped
你可以看到它是愉快地静态链接的。但遗憾的是,并非所有库都可以简单地以这种方式静态链接,并且可能需要使用 libtool
或手动链接目标代码和 C 库进行扩展。
幸运的是,许多嵌入式 C 库,如 musl
为几乎所有( _如果不是全部_)库提供静态链接选项。
现在 strace
您创建的二进制文件,您可以看到在程序开始之前没有访问任何库:
strace ./simpleprog
现在对比一下动态链接程序上 strace
的输出,你会发现静态链接版本的strace要短得多!
原文由 user4832408 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
从源代码(你写的)到可执行代码(你运行的)有两个阶段(在大多数情况下,不考虑解释代码)。
第一个是将源代码转换为目标模块的编译。
第二个,链接,是将对象模块组合在一起以形成可执行文件。
区别在于,允许第三方库包含在您的可执行文件中,而您不会看到它们的源代码(例如用于数据库访问、网络通信和图形用户界面的库),或者用于编译不同语言的代码(例如 C 和汇编代码),然后将它们链接在一起。
当您将文件 静态 链接到可执行文件时,该文件的内容将包含在链接时。换句话说,文件的内容被物理插入到您将运行的可执行文件中。
当您 动态 链接时,指向正在链接的文件的指针(例如文件的文件名)包含在可执行文件中,并且在链接时不包含所述文件的内容。只有当您稍后 运行 可执行文件时,才会购买这些动态链接的文件,并且它们只被购买到可执行文件的内存副本中,而不是磁盘上的那个。
它基本上是一种延迟链接的方法。还有一种 更 延迟的方法(在某些系统上称为后期绑定),在您实际尝试调用其中的函数之前,它不会引入动态链接文件。
静态链接的文件在链接时被“锁定”到可执行文件,因此它们永远不会改变。可执行文件引用的动态链接文件只需替换磁盘上的文件即可更改。
这允许更新功能而无需重新链接代码;每次运行时加载程序都会重新链接。
这既好又坏 - 一方面,它允许更轻松的更新和错误修复,另一方面,如果更新不兼容,它可能导致程序停止工作 - 这有时是某些人可怕的“DLL地狱”的原因提到如果您将动态链接库替换为不兼容的库,则应用程序可能会被破坏(顺便说一句,这样做的开发人员应该期望受到追捕和严厉惩罚)。
作为一个 _例子_,让我们看看用户编译他们的
main.c
文件以进行静态和动态链接的情况。您可以在静态情况下看到主程序和 C 运行时库在链接时(由开发人员)链接在一起。由于用户通常无法重新链接可执行文件,因此他们被库的行为所困扰。
在动态情况下,主程序与 C 运行时导入库链接(它声明了动态库中的内容,但实际上并未 定义 它)。即使缺少实际代码,这也允许链接器进行链接。
然后,在运行时,操作系统加载程序将主程序与 C 运行时 DLL(动态链接库或共享库或其他命名法)进行后期链接。
C 运行时的所有者可以随时插入新的 DLL 以提供更新或错误修复。如前所述,这既有优点也有缺点。