在c++中创建类库时,可以在动态(.dll, .so)和静态(.dll, .so)之间进行选择。Lib, .a)库。它们之间的区别是什么?什么时候使用哪个比较合适?
当前回答
除了静态库与动态库的技术影响(静态文件将所有内容捆绑在一个大的二进制文件中,而动态库允许在几个不同的可执行文件之间共享代码)之外,还有法律影响。
例如,如果您正在使用LGPL许可的代码,并且静态地链接到一个LGPL库(从而创建了一个大的二进制文件),那么您的代码将自动成为开源(自由)LGPL代码。如果您链接到一个共享对象,那么您只需要LGPL对LGPL库本身所做的改进/错误修复。
例如,如果你决定如何编译你的移动应用程序,这就成为一个更重要的问题(在Android中你可以选择静态和动态,在iOS中你不能-它总是静态的)。
其他回答
静态库增加了二进制文件中代码的大小。它们总是被加载,无论你用什么版本的代码编译,都是将运行的代码版本。
动态库的存储和版本是分开的。如果更新被认为与原始版本二进制兼容,则有可能加载的动态库版本不是随代码附带的原始版本。
此外,动态库不一定被加载——它们通常在第一次调用时被加载——并且可以在使用相同库的组件之间共享(多个数据加载,一个代码加载)。
动态库在大多数时候被认为是更好的方法,但最初它们有一个重大缺陷(谷歌DLL地狱),这个缺陷几乎被最近的Windows操作系统(特别是Windows XP)所消除。
静态库必须链接到最终的可执行文件中;它成为可执行文件的一部分,并跟随它到任何地方。每次执行可执行文件时都会加载动态库,并以DLL文件的形式与可执行文件分开。
当您希望能够更改库提供的功能而不必重新链接可执行文件(只需替换DLL文件,而不必替换可执行文件)时,您将使用DLL。
当您没有理由使用动态库时,您可以使用静态库。
c++程序的构建分两个阶段
编译——生成目标代码(.obj) 链接——生成可执行代码(.exe或.dll)
静态库(.lib)只是一个.obj文件的包,因此不是一个完整的程序。它还没有经历构建程序的第二个(链接)阶段。另一方面,dll类似于exe,因此是完整的程序。
如果你构建了一个静态库,它还没有被链接,因此你的静态库的消费者将不得不使用与你使用的相同的编译器(如果你使用g++,他们将不得不使用g++)。
如果相反,您构建了一个dll(并且正确地构建了它),那么您已经构建了一个所有消费者都可以使用的完整程序,无论他们使用哪种编译器。但是,如果需要跨编译器兼容性,则从dll导出有几个限制。
在我们的项目中,我们使用了很多DLL(> 100)。这些DLL相互依赖,因此我们选择了动态链接的设置。然而,它有以下缺点:
启动慢(> 10秒) DLL必须进行版本控制,因为windows根据名称的唯一性加载模块。否则,自己编写的组件将得到错误版本的DLL(即已经加载的DLL而不是自己的分布式集) 优化器只能在DLL边界内进行优化。例如,优化器试图将经常使用的数据和代码放在彼此旁边,但这将不能跨越DLL边界
也许更好的设置是将所有内容都设置为静态库(因此您只有一个可执行文件)。只有在没有发生代码复制的情况下,这才有效。一个测试似乎支持这个假设,但我找不到MSDN的官方引用。例如,创建1个exe:
Exe使用shared_lib1, shared_lib2 Shared_lib1使用shared_lib2 shared_lib2
shared_lib2的代码和变量应该只在最终合并的可执行文件中出现一次。有人能支持这个问题吗?
关于这个主题的精彩讨论,请阅读Sun的这篇文章。
它包含了所有的好处,包括能够插入插入库。关于插入的更多细节可以在这篇文章中找到。
推荐文章
- 什么是“参数依赖查找”(又名ADL,或“Koenig查找”)?
- 公共朋友交换成员函数
- 如何在Go中使用c++
- 自定义c++分配器的引人注目的例子?
- RAII和c++中的智能指针
- 如何构建和使用谷歌TensorFlow c++ api
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 如何为Fedora安装g++ ?
- Std::cin输入空格?
- c++标准是否要求iostreams的性能很差,或者我只是在处理一个糟糕的实现?
- gcc在哪里查找C和c++头文件?
- 为什么我们需要require require ?