C静态库不受欢迎吗?[关闭]


11

共享库有两个参数:

  1. 它有助于减少磁盘空间。
  2. 共享库更新后,取决于它的所有二进制文件都会更新。

共享库主要有一个缺点:

  • 他们可以引入依赖地狱。

在台式计算机上,第一个优点实际上不再成立。如今,浪费磁盘空间已不是什么大问题。

拥有静态二进制文件将使我们能够获得更好的程序包管理器-我的意思是,依赖关系已经成为过去。添加程序就是添加二进制文件。最后是一个文件夹,让它处理其文件。删除程序就是删除该文件。依赖关系?走了

第二个优势仍然存在,但我认为台式机上静态二进制文件的优势胜过它。我的意思是,尽管具有共享库的优势,但即使是Go这样的新语言也可以编译所有二进制文件,这是因为它具有便利性。


既然共享库的主要优点之一不再重要,那么C静态库是否仍然不受欢迎?如果是这样,为什么?


4
不再使用C的主要原因是因为您不在现代台式机上工作。
Telastyn

18
@Telastyn对不起?大多数安装在我的桌面计算机上的软件都写入C.
弗洛里安Margaine

6
侧边-关于该主题的异地阅读- 动态链接被认为有害

6
动态库的一个好处是,人们仍然可以更新库,以解决自15年以来一直停止接收更新的封闭源代码游戏中的错误,安全漏洞或硬件问题。有点小众情况,但是既然好的游戏不是商品,那么“仅仅使用另一个程序”并没有真正的帮助。在不公开采购自己代码的情况下遵守LGPL也很重要。
2014年

4
您忘记了共享库的其他两个优点:1)它们也在内存中共享,2)所有链接器都无法正常使用,并且链接巨大的二进制文件非常不愉快。将二进制文件拆分为几个较小的实体可以使整个过程容忍得多。
SK-logic

Answers:


9

您的问题的前提是有缺陷的。令人信服的是坚持教条和绝对原则,却不了解其背后的基础(货物崇拜编程?)。

链接的SO答案在该主题中是一项有趣的研究-问题是为什么带有-static选项的编译不起作用,您链接到的答案无非是不使用静态链接。如果不讨论其不好的原因,并要求OP使用动态链接。它的不幸之处在于,它被标记为正确答案(后面的答案具有两倍的票数,是对OP的问题的正确答案),因为尽管存在正确的答案,但它深深地隐藏在教条主义的观点之中。

真正的问题是静态链接与动态链接的优缺点是什么,何时会比另一个更受欢迎。


2
Basile的回答确实告诉您他为何建议使用共享库的确切原因:“为什么要静态链接您的应用程序?通常是一个错误(因为您没有从对系统动态库的更新中获利)。特别是名称服务切换libc的工具需要动态库。这不是一个“麻烦”,只是因为您不同意它。
科迪·格雷

@Cody自从我将其称为ant之后,链接到的答案已被编辑。我对静态链接与动态链接的唯一见解是使用适合您需求的链接,并了解选择的优缺点,而不是因为“有人这么说”而陷入了“货物崇拜”编程理论中。
mattnz

是的,添加了“特别是...”部分。不确定如何影响其咆哮状态。当然,我不提倡货物崇拜编程。仅仅是静态链接的支持者(以我的经验)经常会错过或低估安全问题。静态链接非常适合一次性实用程序,从而使应用程序自包含,因此分发起来更加容易。但是任何将被广泛部署或用于生产的应用程序都应该真正链接到共享库。没有真正的缺点:在此应用程序级别,您已经需要一个部署过程。
科迪·格雷

1
我工作的地方就是静态链接适用的一个很好的例子-大型,复杂的生命攸关系统。一旦测试并批准了关键模块的运行,就必须在不经过“过程”的情况下更改其行为。但是,系统的运行和非生命关键部分(计费和报告)都不需要鲁棒的控制,而是使用动态链接。
mattnz

7

从开发人员的角度来看,动态链接通常可以大大加快编译/链接/测试循环的速度。

从软件包管理的角度来看,以libGL为例。我的程序包管理器中提供了大约十二种不同的实现方式,其中一些是通用的,还有一些是针对特定图形卡的。如果它不是动态链接的,则每个程序必须有十几个与libGL链接的版本,否则您将不得不设计一个附加的抽象层,其效率不如函数调用。

考虑一下像Qt这样的流行库中的安全问题。使用动态链接,我可以只更新一个软件包,而不必识别,重新编译和部署Qt中链接的每个软件包。

静态链接在独立部署的封闭源应用程序中可能具有优势,但是在开源软件包管理中,它带来的伤害大于帮助。


2
确实如此(加快了开发速度),但令人沮丧的是它已将其投入生产。典型示例是Firefox。加速动态链接符号解析以使Firefox在合理的时间内加载而付出的大量工程努力(以骇人的骇客形式)。如果他们只愿意静态链接所有项目中的代码(如果需要,还可以动态链接系统库和插件),则可以用更少的工程成本获得更好的性能。
R .. GitHub停止帮助ICE

5

基本上,您的理由#2 是Linux 发行维护者强烈建议使用共享库。对他们来说,真正重要的是,例如,当有人在zlib中发现一个安全漏洞时,他们不必重新编译使用zlib的每个程序-不仅这样做会花费更多的CPU周期重新编译后,使用发行版的每个人都必须重新下载所有这些程序。同时,在发行版提供的一组软件包中,依赖关系地狱不是问题,因为所有内容都经过测试可与该组库一起使用。

如果您要构建需要分发库中没有的库的第三方软件,则静态链接这些库可能比选择替代方法麻烦些,这很好。

要知道的另一件事是,如果库是静态链接的,则GNU libc和GCC libstdc++都具有无法可靠运行的组件。最常见的问题是dlopen,因为您要加载的任何模块dlopen本身都是动态链接的libc.so.6。因此,这意味着现在您在地址空间中拥有C库的两个副本,并且当他们不同意内部malloc数据结构的哪个副本(例如)具有权威性时,就会发生欢喜。更糟糕:不出现功能一大堆有什么关系dlopen,像gethostbynameiconv,使用dlopen在内部(这样它们的行为是可在运行时配置的)。幸运的是,用于libc和libstdc ++的ABI非常稳定,因此您不可能遇到动态链接它们的问题。


2

我同意mattnz的最后一点:这个问题是一个充满挑战的问题。它假定静态链接是错误的。我可以想到以下两个原因:

  • 静态链接是安全的:如果更新了共享库,使得应用程序使用新的库(也许新的库覆盖了旧的库,或者旧的库已被删除),则可能会带来新版本破坏应用程序的风险。这是该应用程序的正式更新范围之外的代码更改。可能尚未经过测试。静态链接通过不与外部共享库来避免这种情况。由于这种风险,我认为这对共享库是不利的。如果共享库的新版本引入了会破坏某些较旧应用程序的新错误,该怎么办?

  • 静态链接可确保应用程序更加独立。虽然共享库可以与主要可执行文件并置,但是它们通常存放在共享位置。静态链接的应用程序更容易确保“可移植”,即“不需要更改操作系统所拥有的文件,目录或设置”(例如Windows目录,注册表,/ etc)。


感谢您改进我要提及的优势。但是,例如,如果您看到Linux发行版提供的大多数软件包,则它们不是静态编译的。这确实似乎是静态编译令人难以接受的,从外部来看,至少。
Florian Margaine 2014年

1
这些天来,几乎每一个OS上的动态库都按需求进入。只有实际使用的页面在内存中。如果多个应用程序使用相同的功能,则它们将共享内存并且使用的空间少于静态库的情况。如果多个应用程序在同一个库中使用不同的功能,则这两组功能将被调入页面,其影响与静态方法大致相同。
艾伦·舒特科

@AlanShutko由于您提到的内容,我确实很努力并用几种方式重新输入了该部分。即使现代操作系统在实践中确实提供了共享库的效率以及静态开销,也没有任何一种真正的保证。我将再次编辑。

@Snowman我认为基本要点是,在提供动态链接的任何实际操作系统上(我不知道任何使用动态链接但不要求分页的OS),第二点没有用:实际未使用内存除非使用了该函数,否则动态库使用的内存可以在使用它的不同程序之间共享,从而使动态版本的内存使用效率更高,而不是更低。您的第一个和第三个原因是正确的,但我只删除第二个原因:以任何现实的假设,这都是错误的。
Jules 2014年

@Jules我同意,这一点在现代操作系统中是有问题的,并且具有可疑的有效性。我删除了

1

静态和动态库都有各自的用途。查看范围内的单个应用程序,我们对需要什么和不需要什么有了不同的想法。

静态链接极大地简化了应用程序部署。不必检测和处理不同的版本。刚烘烤并部署。

动态库的明显优势是能够独立应用更新。

这就是我讨厌Maven和其他类似的Java动态链接项目构建器的原因之一。他们希望在指定的URL上永远可以使用单个库版本。由于所有源和jar都已消失,因此没有人理解十年来出现的问题,当时没人能编译该应用程序。


是否有任何特殊原因为什么过去的程序FooLib1.8无法以标准方式在其可执行程序包中包含该库的代码,从而允许附带的升级实用程序对其FooLib1.9进行升级或降级?将代码存储在Classic Macintosh中的方式使这变得非常容易。当今的系统是否有任何理由不应该做得更好?
2014年

@supercat您的意思是给定库的每个版本都可以在系统上使用?不知道我明白这个问题。OP问题更多地针对系统范围的共享库,而不是打包在一起的静态库。
很多薯片

我的观点是,拥有一个可执行软件包,其中包括它需要的所有库,都不必排除升级其中包含的库的可能性。因此,我不知道我会考虑将部署后升级的能力视为不将应用程序与其库捆绑在一起的优势。
2014年

如果给定库的许可证允许您将其与软件包一起分发,那么这始终是首选的方式。它减少了外部依赖项的数量。由于您将分发所有内容,因此升级或修补机制将以静态或动态方式运行。通常基于二进制增量进行修补。不会有任何区别。
很多薯片
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.