静态库和共享库的区别是什么?

683

静态库和共享库有什么区别?

我使用的是Eclipse,其中包括静态库和共享库等多种项目类型。它们之间是否存在优劣之分?


4
维基百科对于静态、动态和共享库的区别有一个良好的描述。 - Adam Holmberg
9个回答

885

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

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

每种方法都有优缺点:

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

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

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


2
用具有相同功能的共享对象替换...,但可能会[提高]性能:特别是在API(应用程序编程接口:函数签名和变量,包括类型)的语义使用中具有等效的调用方面功能,但实现方面的功能可能不同,例如:函数始终记录到文件->也记录到TCP服务器:端口预期在$MY_APP_LOG_SERVER中。 - Tony Delroy
2
由于代码在编译时连接,因此没有额外的运行时加载成本。代码就在那里。是和否...它们都在可执行映像中,如果执行需要,就可以分页调入,但是——从程序最近未运行到缓存的情况开始——使用共享库时,操作系统、驱动程序或另一个正在运行的程序可能已经加载了您的应用程序要使用的相同共享库,在这种情况下,它可能已经在缓存中,您的程序启动和运行速度更快。 - Tony Delroy
49
有些人没有提及的是,对于静态库,编译器知道你的应用程序需要哪些函数,然后只包含这些函数进行优化。这可以大大减小库的大小,特别是如果你只使用一个非常大的库的一个非常小的子集时! - jduncanator
2
这个答案可以更好地组织。制作优缺点的项目列表或表格以显示每个维度的差异将非常有帮助。 - ElefEnt
2
当您进行动态编译时,您正在声明一个在运行时解决的依赖项。满足此依赖关系需要(a)将库的副本与程序一起携带,或者(b)确保在运行之前在目标系统上安装库。这意味着程序的部署变得更加复杂。静态链接将所有这些依赖项放入编译时的程序中,因此通常将部署减少为单个文件。 - Anya Shenanigans
显示剩余4条评论

435

静态库就像一家书店,而共享库就像一家图书馆。使用前者,您可以获得自己的书 / 函数副本带回家;而对于后者,您和其他人都必须去图书馆使用同一本书/函数。因此,想要使用(共享的)库的任何人都需要知道它在哪里,因为您必须“取得”这本书/函数。使用静态库时,这本书/函数归您所有,您将其保留在自己的家庭/程序中,一旦拥有它,您不再关心它在何时何地获取。


104

简化版:

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

55
对于静态库,链接器从库中提取代码,并在编译/构建应用程序时用于构建最终可执行文件。最终的可执行文件在运行时不依赖于库。
对于共享库,编译器/链接器在构建应用程序时检查您链接的名称是否存在于库中,但不将它们的代码移动到应用程序中。在运行时,必须可用共享库。
C编程语言本身没有静态库或共享库的概念-它们完全是实现特性。
个人而言,我更喜欢使用静态库,因为它使软件分发更简单。然而,这是一个关于过去已经流传了很多争议的观点。

14
+1 对于 "C编程语言本身没有静态库或共享库的概念 - 它们完全是实现功能。" - Tiger
1
嗨,anon / @Tiger,为什么您说:“C编程语言本身没有静态库或共享库的概念-它们完全是一种实现特性。”? 您能否详细解释一下或指向适当的参考资料? - Sunil Shahu
@SunilShahu 程序的编译和链接方式取决于您使用的编译器和链接器,即语言的具体实现。语言规范通常不描述语言应如何实现或构建,只描述其功能、语法、语法等。 - user4396006
@SunilShahu 更明显的例子可能是JavaScript,例如,规范(EcmaScript)描述了语言的特性,但是不同的供应商提供JS解释器(例如浏览器引擎或Node.js)。另一方面,Python编程语言有几个实现。官方的是CPython,但也有其他用其他语言编写的实现。 - user4396006

36

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

静态库的优点是用户在运行应用程序时不需要任何依赖项,例如他们不必升级其DLL。缺点是因为您将它与所有所需库一起发布,所以您的应用程序大小会更大。

除了导致较小的应用程序之外,共享库还为用户提供了使用自己可能更好的库版本的能力,而不是依赖于应用程序中的一个版本。


3
DLL地狱,正如它被称呼的那样。 - gheese
1
"静态库是作为应用程序的一部分编译的" ... 静态库被编译为静态库,并作为应用程序的一部分链接。 - 463035818_is_not_a_number

24

共享库最重要的优点是无论有多少进程使用该库,内存中只加载一份代码副本。而静态库每个进程都会获得自己的代码副本,这可能导致显著的内存浪费。

另一方面,静态库的一个优点是所有内容都被打包到应用程序中。因此,您不必担心客户端在其系统上是否有正确的库(和版本)可用。


1
当使用静态库时,可执行映像在磁盘和内存中都会变得更大。 - JustJeff
没错,当我说一切都捆绑在您的应用程序中时,我就是在暗示这个。 - Jasmeet
此外,在*nix系统上,.so文件是一种共享(动态)库。 - Soner from The Ottoman Empire

9
除了其他答案之外,还有一件事没有提到,那就是解耦:
让我谈谈我曾经处理过的真实生产代码:
一个非常庞大的软件,由超过300个项目(使用Visual Studio)组成,大多数被构建为静态库,最终全部链接在一个巨大的可执行文件中,你会遇到以下问题:
- 链接时间非常长。你可能需要15分钟以上的链接时间,而编译时间只有10秒。 - 某些工具无法处理如此大的可执行文件,例如必须插入代码的内存检查工具。你可能会达到被视为愚蠢的极限。
更为棘手的是软件解耦:在这个真实的例子中,每个项目的头文件都可以从任何其他项目中访问。因此,一个开发人员很容易添加依赖项;只需包含头文件,因为最后链接时将始终找到符号。这最终导致了可怕的循环依赖和完全混乱。
使用共享库需要一些额外的工作,因为开发者必须编辑项目构建系统以添加依赖库。我观察到,共享库代码往往提供更清晰的代码API。

5
+---------------+---------------------------+------------------------------+
| properties    | Static library            | Shared library               |
+===============+===========================+==============================+
| Linking time  | It happens as the         | Shared libraries             |
|               | last step of the          | are added during             |
|               | compilation process.      | linking process              |
|               | After the program         | when executable              |
|               | is placed                 | file and libraries           |
|               | in the memory             | are added to the memory.     |
+---------------+---------------------------+------------------------------+
| Means         | Performed by linkers      | Performed by operating System|
+---------------+---------------------------+------------------------------+
| Size          | Static libraries are      | Dynamic libraries are        |
|               | much bigger in size,      | much smaller, because        |
|               | because external          | there is only one copy       |
|               | programs are built        | of dynamic library           |
|               | in the executable file.   | that is kept in memory.      |
+---------------+---------------------------+------------------------------+
| External file | Executable file will      | In shared libraries,         |
| changes       | have to be recompiled     | no need to recompile         |
|               | if any changes were       | the executable.              |
|               | applied to external files.|                              |
+---------------+---------------------------+------------------------------+
| Time          | Takes longer to execute   | It is faster                 |
|               | because loading into the  | because shared               |
|               | memory happens every time | library code is              |
|               | while executing.          | already in the memory.       |
+---------------+---------------------------+------------------------------+
| Compatibility | Never has a compatibility | Programs are dependent       |
|               | issue,since all code is   | on having a compatible       |
|               | in one executable module. | library.Dependent program    |
|               |                           | will not work if library     |
|               |                           | gets removed from the system |
+---------------+---------------------------+------------------------------+

3
-------------------------------------------------------------------------
|  +-  |    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  |                                     |
-------------------------------------------------------------------------

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接