静态库与动态库的区别
- 静态库
- 动态库
首先用OpenCV的开源库来举个例子了解一下库文件的分类:
bin文件夹里面放的都是dll文件;
lib文件夹里面放的都是伴随dll文件的动态lib文件;
staticlib文件夹里面放的才是真正的静态lib文件,和dll文件是独立的,没有任何关系的;
所以可以看出,lib文件是有静态lib和动态llib之分的。
了解了库文件的分类后,我们开始学习静态库与动态库的区别
静态库
什么是静态库?
一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件,如果你工程里只有一个lib.h和lib.cpp,那么编译后产生的lib文件实际上就是这一个lib.obj文件的一个集合,但是如果你工程里还有其他的很多个lib.cpp文件,那么就会在编译之后生成许多lib.obj文件,然后最终只链接生成一个静态lib文件,这就是静态库。也正是因为静态库中包含了所有的静态库的.obj文件,所以静态库包含了函数的完整实现。
为什么叫作静态库?
之所以称为静态库,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,如果静态库需要进行修改,那么需要将修改的静态库文件和目标文件重新链接打包到可执行文件中,因此对应的链接方式称为静态链接,对应的库就是静态库。
静态库特点总结:
- 引用静态库时,在编译阶段会将静态lib文件和其他obj文件打包生成.exe可执行文件,因为静态库是任意个obj文件的集合,所以静态库包含了函数代码的完整实现,所以这里的.exe文件可以直接执行。以后再运行这个exe可执行文件时,也不再需要.lib文件,可以直接运行
- 浪费空间和资源,因为静态lib文件实际上是包含了所有的导出声明和实现,你如果把这个lib文件链接到自己的程序之后,这个lib文件中的所有代码都会嵌入进来,哪怕你只用到了其中一部分,剩下没用到的也进了你的代码。这就不难想象会造成的后果了,虽然方便,但是如果大部分你都用不到,自然会导致你的库体积没有意义地变大。
- 当静态链接库发生变化时,目的程序必须要重新编译,否则执行时静态链接库的内容没有更新,重新编译后再发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
什么场合下适用静态库:
因为静态链接库会使得.exe文件的size变大,并且相对于动态链接库运行速度更快。故静态链接库适用于小型应用的开发。
动态库
为什么需要动态库?
其实也是静态库的特点导致。空间浪费是静态库的一个问题,另一个问题是静态库的更新问题。
什么是动态库?
一个dll工程生成一个dll文件的时候,总是伴随着生成一个lib文件,这个lib文件其实是一个动态的lib,它的大小比静态lib要小很多,动态链接库中的动态.lib并不包含由.cpp生成的目标文件,目标文件都包含在.dll中,.lib仅仅是提供链接到.DLL的地址信息等,即动态lib文件其实只是包含了一些函数索引信息,记录了dll中那些函数的入口和位置,dll中才是具体的函数实现。所以对于动态链接库来说,.lib和.dll缺一不可。主要体现在:在编译时如果你加了.lib的依赖项,不会出任何问题,但运行时,若没有.dll,会提示找不到xx.dll的信息。
为什么叫作动态库?
在编译阶段这个过程只需要用到这里的动态lib文件,然后将动态lib文件和你的代码打包到一起生成.exe可执行文件,动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,在运行期间,使用到动态库中的函数时,会通过动态.lib文件记录的函数索引信息找到函数正确的位于dll中的位置,然后直接执行那些函数就行了。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库(动态库可以实现进程之间的资源共享,因此动态库也称为共享库)所对应的动态lib文件,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新,是动态的。
正常情况下,发行一个软件的过程应该是这样的:
你的项目分成独立的几个模块,每个模块都有一个dll文件,然后有一个最终的程序入口exe文件,最后把dll文件和exe文件发行给用户。当用户每次点击这个exe文件的时候,自然会动态调用用到的dll文件。注意这个过程就不再需要什么.h和.lib了,那是别人调用你的库,再进行加工写代码时才需要做的事。上面说过dll其实就是个不能单独打开执行的exe而已,所以你最终发行给用户的只能是dll和exe(exe中包含了动态.lib文件,程序运行时通过动态.lib文件找到dll文件中相应函数的位置),当然你完全可以把所有的东西只打包在一个exe中。但是当你的软件非常大的时候,这样进行更新维护就非常不方便,如果有问题就得重新发行一次exe,但是如果把各个模块单独弄成dll,你只需要打个补丁(更新dll文件),然后对那些有问题的dll进行更换就行了。
调用动态库需要这些文件:
如果我们需要调用一个动态库,我们就需要.h文件,.lib文件,.dll文件,然后如果.dll文件封装的函数代码有改动,只需要重新编译一次dll,替换掉原来的dll就可以了,非常方便!!!当然前提是,这个动态库的函数接口写得好。进行修改时只需要修改内部实际的代码,并不需要对接口改来改去!
什么场合下适用动态链接库:
- 因为静态链接库是和目标文件一起打包成为一个.exe可执行文件,所以该可执行文件不能链接其它链接库,无论静态库或者动态链接库。所以,当该当链接库还需要链接其它的链接库,包括静态或者动态链接库的场合,应该使用动态链接库。
- 当库可能需要进行修正时,可以选择使用动态库,这样其应用程序不需要再次编译,只需要更新该.dll文件,然后替换掉旧的.dll文件即可,可以减少软件的耦合。
- 由于动态链接库.dll可以链接到不同编程语言的工程,所以对于多语言的软件开发的场合也是适用的。
- 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
参考资料:
https://blog.csdn.net/carlhelen/article/details/85157022?spm=1001.2014.3001.5506
https://blog.csdn.net/hm_123123123/article/details/125271876?spm=1001.2014.3001.5506
https://tool.4xseo.com/a/54522.html