10

我最近在这里阅读了一个关于静态和动态链接的问题,这让我想起了一些关于它的问题。从那篇文章中,我可以看到技术差异是什么(直接包括目标文件内容,而不是仅仅指向它),但我想更多地了解这样做的利弊。

前段时间,我的一位从事编程多年的朋友感叹 C# 没有静态链接,并说这是他未来版本最想要的功能。不幸的是,我是新手,并不真正理解这种说法。

感谢您的任何启发!

4

5 回答 5

9

静态链接的优点是它消除了对库的外部依赖——也就是说,您正在使用的库的行为永远不会改变,因为有人更改了磁盘上的库。这也是静态链接的缺点之一。如果操作系统发生变化并且需要新版本的库才能正常工作,则必须提供二进制文件的升级版本。同样,如果将错误修复添加到库中,如果您已静态链接,则不会自动获得该错误修复。

大多数(事实上,可能是所有这些天)操作系统可以为多个进程加载一个动态库的副本,这就是为什么在 UNIX 上它们被称为共享对象。

于 2008-11-23T11:38:58.677 回答
7

静态可执行文件包含它需要的所有对象,因此在执行时不会调用外部 DLL。优点是可以跨许多平台移植,无论该系统上安装了什么版本的 DLL。最大的缺点是您可能会浪费磁盘空间,因为您包含在系统/外部 DLL 中已经存在的可执行代码中。此外,我认为,但我不太确定,DLL 在主内存中只加载一次,无论有多少可执行文件正在使用它们,但是如果你静态链接可执行文件中的库对象,你会加载相同的代码两次(一个用于其余程序使用的 DLL 和一个用于您的可执行文件的 DLL)。另一方面,这可能是一个优势而不是一个劣势,因为可执行文件只包含它需要的外部库的对象,而不是整个库。当应用程序需要 DLL 时,它会作为一个整体加载到内存中。

静态链接非常适合编译您希望作为小工具从一个系统携带到另一个系统的小型应用程序。也就是说,当它没有包含在每个 Linux 发行版中时,拥有一个静态编译版本的 tcpdump 对我来说真的很有用。无论内核、glibc 或其他系统库有什么版本,它都必须在每个 Linux 上工作。也许它在 Windows 世界中没有多大意义,因为平台更加同质化。如果您为 Windows XP / NET vX.X 进行编译,它将适用于许多计算机。如果您为 Debian XX 编译某些东西,它肯定无法在较旧/较新的 Debian 或其他发行版(如 Redhat)上运行。

这个帖子也可以解决你的问题。

于 2008-11-23T11:36:24.033 回答
6

老实说,出于一百万个原因,我不确定静态链接在 C# 中是否真的是一个好主意。一个原因是,与 C 或 C++ 等语言相比,C# 具有程序集的概念,程序集基本上是可执行文件或 DLL。

现在,如果您想在 .NET 中静态链接事物,您要么

  • 将多个程序集中的类合并到一个程序集中。这会破坏很多东西,比如“内部”访问修饰符。
  • 在同一个可执行文件中有多个程序集。但是,这将使程序集的整个概念变得毫无用处,并且需要重新设计 .NET Framework 中的反射方法。

我确信有一种巧妙的方法可以避免这些问题,但我不太明白在 .NET 或 Java 等托管环境中进行静态链接的意义。我的意思是,静态链接确实可以提高性能,但并没有那么多。无论如何,我们不会使用托管语言来提高它们的执行速度。

另一个问题是 DLL 地狱,但在 .NET 中,这几乎是一个已解决的问题。

于 2008-11-23T12:05:39.107 回答
3

所有需要的东西都打包成一个可执行文件。所以,

  • 你不需要安装任何其他的东西。只需复制并运行。或者跑到它所在的地方。没有安装程序,没有警告,没有由于错误的 DLL 版本而导致的奇怪错误。就这样。
  • 您的用户也可以享受这种简单性。这通常更为重要。没有人欢迎安装依赖项。特别是如果它像 .NET 框架一样庞大。

当然可执行文件的大小会增加,但它应该小于一堆愚蠢的图形文件。

于 2013-11-10T02:57:28.777 回答
1

有一个很好的例子来说明静态链接和动态链接之间的区别。如果您查看 InkScape 项目,您会发现InkscapePortable和 InkScape。InkscapePortable 将使用 USB 记忆棒运行。InkScape 不会。

于 2012-03-15T16:28:23.343 回答