静态库和共享库之间的区别?


Answers:


745

共享库是.so(或Windows .dll或OS X .dylib)文件。与该库有关的所有代码都在此文件中,并且运行时使用它的程序会引用它。使用共享库的程序仅引用其在共享库中使用的代码。

静态库是.a(或在Windows .lib中)文件。与库有关的所有代码都在此文件中,并且在编译时直接链接到程序中。使用静态库的程序从静态库获取其使用的代码的副本,并将其作为程序的一部分。[Windows也有用于引用.dll文件的.lib文件,但它们的作用与第一个相同。]

每种方法都有优点和缺点:

  • 共享库减少了使用该库的每个程序中重复的代码量,从而使二进制文件较小。它还允许您用功能上等效的共享对象替换共享对象,但可能会增加性能优势,而无需重新编译使用共享对象的程序。但是,共享库将为函数的执行带来少量的额外成本以及运行时的加载成本,因为库中的所有符号都需要连接到它们使用的事物。另外,可以在运行时将共享库加载到应用程序中,这是实现二进制插件系统的通用机制。

  • 静态库增加了二进制文件的整体大小,但这意味着您无需携带正在使用的库的副本。由于代码是在编译时连接的,因此没有任何额外的运行时加载成本。代码就在那里。

就个人而言,我更喜欢共享库,但是在需要确保二进制文件没有很多可能难以满足的外部依赖项时使用静态库,例如C ++标准库的特定版本或Boost C ++库的特定版本。


2
“用...在功能上等效的共享对象,但可以[提高]性能”:具体来说,在API的语义使用中等效的面向调用者的功能(应用程序编程接口:函数签名和包括类型的变量),但在实现方面功能可能与性能不同。例如,功能总是记录到文件->也记录到$ MY_APP_LOG_SERVER中期望的TCP服务器:端口。
Tony Delroy 2014年

1
“ [.sos会为执行功能带来少量的额外成本””-这是可能的(如果针对静态链接中的缓存局部性优化了功能组/顺序,或者由于OS / loader / compiler / architecture之类的交叉-segment /大指针性能损失),但在许多体系结构/编译器设置中,动态链接程序会修补调用以创建完全相同的调用计算机操作码。
Tony Delroy 2014年

2
“由于代码是在编译时连接的,因此没有任何额外的运行时加载成本。代码就在那里。” -是和否...如果需要执行,所有内容都可以在可执行映像中分页,但是-从您的程序最近运行得不够快而无法缓存的情况开始-使用共享库是可能的(有时可能(或确定)操作系统,驱动程序或其他正在运行的程序将已经加载了您的应用要使用的相同的共享库,在这种情况下,它可能位于缓存中,并且程序启动和运行速度更快。
Tony Delroy 2014年

15
某些人没有提到的是,使用静态库,编译器知道您的应用程序需要哪些功能,然后仅包含那些功能就可以对其进行优化。这可以大大减少库的大小,特别是如果您仅使用很大的库的很小一部分的话!
jduncanator 2014年

1
这个答案可以更好地组织起来。列出有利/不利事项的项目符号列表或表格,以显示存在差异的每个维度的差异,这将很有帮助。
ElefEnt '16

377

静态库就像书店,共享库就像...库。使用前者,您可以获得自己的书/功能副本,可以带回家。对于后者,您和其他所有人都去图书馆使用相同的书/功能。因此,任何想要使用(共享)库的人都必须知道它的位置,因为您必须“去获取”这本书/功能。有了静态库,您就可以拥有这本书/函数,并将其保存在自己的家庭/程序中,一旦拥有它,就不必在意何时何地。


70

简化:

  • 静态链接:一个大型可执行文件
  • 动态链接:一个小的可执行文件,再加上一个或多个库文件(在Windows上为.dll文件,在Linux上为.so,在macOS上为.dylib)

1
这个答案对我来说是最好的,因为它很实用。这比不谈论计算机实际发生的隐喻更具意义。知道发生了什么之后,我凭直觉就知道了所有其他含义。
off99555

36

对于静态库,链接器从库中提取代码,并将其用于在编译/构建应用程序时构建最终的可执行文件。最终可执行文件在运行时不依赖库

对于共享库,编译器/链接器会在构建应用程序时检查与您链接的名称是否存在于库中,但不会将其代码移入应用程序。在运行时,共享库必须可用。

C编程语言本身没有静态库或共享库的概念-它们完全是一种实现功能。

就个人而言,我更喜欢使用静态库,因为它使软件分发更简单。但是,这是过去关于大量(象征性)流血的观点。


5
+1表示“ C编程语言本身没有静态或共享库的概念-它们完全是一种实现功能。”
老虎

1
您好,anon / @Tiger,为什么您说“ C编程语言本身没有静态库或共享库的概念-它们完全是一种实现功能。”?您能否详细解释一下,或为我提供适当的参考?
苏尼尔·沙湖

@SunilShahu程序的编译和链接方式特定于您使用的编译器和链接器,即该语言的特定实现。语言speficications一般不描述如何语言应实施或建成,只有功能,句法,语法等
JC Rocamonde

@SunilShahu更明显的示例可能是JavaScript,例如,规范(EcmaScript)描述了该语言的功能,但JS解释器(例如,浏览器引擎或Node.js)是由不同的供应商提供的。另一方面,Python编程语言具有多种实现。官方的是CPython,但是还有其他用其他语言编写的。
罗卡蒙德

31

静态库作为应用程序的一部分进行编译,而共享库则不是。当您分发依赖共享库的应用程序时,这些库例如。需要在MS Windows上安装dll。

静态库的优点是运行应用程序的用户不需要依赖项-例如,他们不必升级其DLL。缺点是您的应用程序较大,因为您将其附带所有需要的库。

共享库除了导致更小的应用程序外,还使用户能够使用自己的,也许是更好的版本的库,而不必依赖于应用程序一部分


3
众所周知的DLL地狱
gheese 2013年

1
“静态库被编译为应用程序的一部分” ...静态库被编译为静态库并作为应用程序的一部分链接
idclev 463035818

19

共享库的最大优点是,无论使用该库的进程有多少,内存中仅加载一个代码副本。对于静态库,每个进程都会获得自己的代码副本。这会导致大量的内存浪费。

OTOH,静态库的一个优点是所有内容都捆绑到您的应用程序中。因此,您不必担心客户端在其系统上将具有正确的库(和版本)。


1
使用静态库时,可执行映像在磁盘和内存中更大。
JustJeff 2010年

没错,这就是我所说的一切都捆绑到您的应用程序中时所暗示的含义。
Jasmeet 2010年

另外,.so* nix系统上的文件有点是共享(动态)库。
snr

6

除了所有其他答案之外,还没有提到的一件事就是去耦:

让我说说我一直在处理的真实世界的生产代码:

一个很大的软件,由300多个项目组成(使用Visual Studio),主要是作为静态库构建的,最后都链接到一个巨大的可执行文件中,最终会遇到以下问题:

-链接时间非常长。您可能最终会花费超过15分钟的链接时间,例如10秒钟的编译时间-一些工具拥有如此大的可执行文件,例如必须检查代码的内存检查工具。您可能会陷入被视为傻瓜的极限。

更麻烦的是软件的解耦:在这个实际的示例中,每个项目的头文件都可以从其他任何项目访问。结果,一个开发人员添加依赖非常容易。它只是包含标题,因为结尾处的链接将允许查找符号。它以可怕的循环依赖和完全混乱而告终。

对于共享库,这需要一些额外的工作,因为开发人员必须编辑项目构建系统以添加从属库。我观察到共享库代码倾向于提供更简洁的代码API。


2
-------------------------------------------------------------------------
|  +-  |    Shared(dynamic)       |   Static Library (Linkages)         |
-------------------------------------------------------------------------
|Pros: | less memory use          |   an executable, using own libraries|
|      |                          |     ,coming with the program,       |
|      |                          |   doesn't need to worry about its   |
|      |                          |   compilebility subject to libraries|
-------------------------------------------------------------------------
|Cons: | implementations of       |   bigger memory uses                |
|      | libraries may be altered |                                     |
|      | subject to OS  and its   |                                     |
|      | version, which may affect|                                     |
|      | the compilebility and    |                                     |
|      | runnability of the code  |                                     |
-------------------------------------------------------------------------
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.