在c++中创建类库时,可以在动态(.dll, .so)和静态(.dll, .so)之间进行选择。Lib, .a)库。它们之间的区别是什么?什么时候使用哪个比较合适?


当前回答

其他人已经充分解释了静态库是什么,但我想指出一些使用静态库的注意事项,至少在Windows上:

Singletons: If something needs to be global/static and unique, be very careful about putting it in a static library. If multiple DLLs are linked against that static library they will each get their own copy of the singleton. However, if your application is a single EXE with no custom DLLs, this may not be a problem. Unreferenced code removal: When you link against a static library, only the parts of the static library that are referenced by your DLL/EXE will get linked into your DLL/EXE. For example, if mylib.lib contains a.obj and b.obj and your DLL/EXE only references functions or variables from a.obj, the entirety of b.obj will get discarded by the linker. If b.obj contains global/static objects, their constructors and destructors will not get executed. If those constructors/destructors have side effects, you may be disappointed by their absence. Likewise, if the static library contains special entrypoints you may need to take care that they are actually included. An example of this in embedded programming (okay, not Windows) would be an interrupt handler that is marked as being at a specific address. You also need to mark the interrupt handler as an entrypoint to make sure it doesn't get discarded. Another consequence of this is that a static library may contain object files that are completely unusable due to unresolved references, but it won't cause a linker error until you reference a function or variable from those object files. This may happen long after the library is written. Debug symbols: You may want a separate PDB for each static library, or you may want the debug symbols to be placed in the object files so that they get rolled into the PDB for the DLL/EXE. The Visual C++ documentation explains the necessary options. RTTI: You may end up with multiple type_info objects for the same class if you link a single static library into multiple DLLs. If your program assumes that type_info is "singleton" data and uses &typeid() or type_info::before(), you may get undesirable and surprising results.

其他回答

如果您的库将在几个可执行文件之间共享,那么将其动态化以减少可执行文件的大小通常是有意义的。否则,一定要让它是静态的。

使用dll有几个缺点。装载和卸载它有额外的开销。还有一个额外的依赖关系。如果您更改dll使其与执行表不兼容,则它们将停止工作。另一方面,如果您更改了静态库,则使用旧版本编译的可执行文件将不会受到影响。

其他人已经充分解释了静态库是什么,但我想指出一些使用静态库的注意事项,至少在Windows上:

Singletons: If something needs to be global/static and unique, be very careful about putting it in a static library. If multiple DLLs are linked against that static library they will each get their own copy of the singleton. However, if your application is a single EXE with no custom DLLs, this may not be a problem. Unreferenced code removal: When you link against a static library, only the parts of the static library that are referenced by your DLL/EXE will get linked into your DLL/EXE. For example, if mylib.lib contains a.obj and b.obj and your DLL/EXE only references functions or variables from a.obj, the entirety of b.obj will get discarded by the linker. If b.obj contains global/static objects, their constructors and destructors will not get executed. If those constructors/destructors have side effects, you may be disappointed by their absence. Likewise, if the static library contains special entrypoints you may need to take care that they are actually included. An example of this in embedded programming (okay, not Windows) would be an interrupt handler that is marked as being at a specific address. You also need to mark the interrupt handler as an entrypoint to make sure it doesn't get discarded. Another consequence of this is that a static library may contain object files that are completely unusable due to unresolved references, but it won't cause a linker error until you reference a function or variable from those object files. This may happen long after the library is written. Debug symbols: You may want a separate PDB for each static library, or you may want the debug symbols to be placed in the object files so that they get rolled into the PDB for the DLL/EXE. The Visual C++ documentation explains the necessary options. RTTI: You may end up with multiple type_info objects for the same class if you link a single static library into multiple DLLs. If your program assumes that type_info is "singleton" data and uses &typeid() or type_info::before(), you may get undesirable and surprising results.

除了其他人提到的所有要点,我在特定的用例中使用静态库:

不允许我的终端用户访问一些通用库 我在我的代码中开发的。

换句话说,假设我的产品中有两个库,A和B。A使用B服务并依赖于它。但是B是一个通用库,包括许多可以单独使用的有用服务。为了避免我的终端用户直接从B中受益(他们应该为B的许可证付费!),我通常将B编译为一个静态库,并将其直接放在a中。因此,B服务对a来说是完全私有的,最终用户不能使用。

除了静态库与动态库的技术影响(静态文件将所有内容捆绑在一个大的二进制文件中,而动态库允许在几个不同的可执行文件之间共享代码)之外,还有法律影响。

例如,如果您正在使用LGPL许可的代码,并且静态地链接到一个LGPL库(从而创建了一个大的二进制文件),那么您的代码将自动成为开源(自由)LGPL代码。如果您链接到一个共享对象,那么您只需要LGPL对LGPL库本身所做的改进/错误修复。

例如,如果你决定如何编译你的移动应用程序,这就成为一个更重要的问题(在Android中你可以选择静态和动态,在iOS中你不能-它总是静态的)。

静态库被编译到客户机中。在编译时使用.lib,库的内容成为消费可执行文件的一部分。

动态库在运行时加载,而不是编译到客户端可执行文件中。动态库更加灵活,因为多个客户端可执行文件可以加载一个DLL并利用它的功能。这也将客户端代码的总体大小和可维护性保持在最小。