ChatGPT解决这个技术问题 Extra ChatGPT

静态库和共享库的区别?

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

我使用 Eclipse,有几种项目类型,包括静态库和共享库?一个比另一个有优势吗?

Wikipedia 对静态库、动态库和共享库有good description的区别。

P
Paolo

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

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

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

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

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

个人比较喜欢共享库,但是在需要保证二进制没有太多可能难以满足的外部依赖的时候使用静态库,比如特定版本的C++标准库或者特定版本的Boost C++库。


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

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


C
CraftedCart

简化:

静态链接:一个大型可执行文件

动态链接:一个小的可执行文件加上一个或多个库文件(Windows 上的 .dll 文件、Linux 上的 .so 或 macOS 上的 .dylib)


佚名

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

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

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

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


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

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

静态库的优点是运行应用程序的用户不需要依赖项——例如,他们不必升级他们的 DLL。缺点是您的应用程序体积较大,因为您将它与它需要的所有库一起提供。

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


众所周知的 DLL 地狱
“静态库被编译为应用程序的一部分”......静态库被编译为静态库并作为应用程序的一部分链接
J
Jasmeet

共享库最显着的优势是,无论有多少进程在使用该库,内存中都只加载了一份代码副本。对于静态库,每个进程都有自己的代码副本。这会导致显着的内存浪费。

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


使用静态库时,可执行映像在磁盘和内存中都更大。
没错,当我说所有东西都捆绑到您的应用程序中时,这就是我所暗示的。
此外,*nix 系统上的 .so 文件是一种共享(动态)库。
s
sandwood

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

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

一个非常大的软件,由超过 300 个项目(使用 Visual Studio)组成,主要构建为静态库,最后全部链接到一个巨大的可执行文件中,您最终会遇到以下问题:

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

更成问题的是您的软件的解耦:在这个真实世界的示例中,每个项目的头文件都可以从任何其他项目中访问。因此,一位开发人员非常容易添加依赖项。它只是包括标题,因为最后的链接会找到符号。它以可怕的循环依赖和完全混乱而告终。

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


s
snr
-------------------------------------------------------------------------
|  +-  |    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  |                                     |
-------------------------------------------------------------------------

s
sun1211
+---------------+---------------------------+------------------------------+
| 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 |
+---------------+---------------------------+------------------------------+