动态链接库

  一直在用库,也一直不知道到啥是库。今天有时间,就了解一下库吧!(以动态链接库为题,但内容中也相关与静态库)。

  希望能通过这篇博客,说明白这么几个问题:

   1. 什么是静态链接库?什么是动态链接库?

   2. 静态链接库和动态链接库的区别(两者各自的优点,缺点)?

   3. 动态链接库的调用方式(隐式调用,显式调用两者区别及优缺点)。

   4. 关于链接库一些相关的文件说明(比如.lib,.dll等)。

一、什么是静态链接库,什么是动态链接库?+ 二、两者区别

  要想明白两者,先要懂什么是库。在写程序中,我们经常调库。所谓的库我理解就是共享程序,别人写好的指定功能的程序可以被自己拿来用去完成自己的功能(好吧,有点绕)。那我们是怎么能够用别人写的库的呢?这就自然而然的引出了链接库的概念。

  静态链接库(static link library)指的是以静态的方式调用库中的某一个函数。那什么是静态的方式呢?静态就是指在主程序编译的时候,遇到了需要静态库中函数的地方,就把静态库中的函数导入文件中。直到文件结束,把所有的部分(包括静态库的函数)都放到可执行程序中。(一股脑全都放进去,听起来笨笨的)

  动态链接库(dynamic link library)就是动态的方式啦!动态就是在程序编译的时候,即使发现了你需要动态库里面的函数。但是鉴于你现在并没有运行(不是真正的需要)。所以暂时先不放到你的可执行程序中。当可执行程序执行时并且到了调用动态库函数的时候,再去找到对应的函数,给输入得输出。

  那二者之间的区别如何呢?孰优孰劣,且听我慢慢道来!

  静态链接库的优点

  1. 可执行程序运行时速度较快
    前面提到,所有要用的函数都已经在自己的程序里面了。直接拿来用比用的时候去找自然快了很多。

  2. 不需要担心版本问题
    这个其实我不是特别懂,但我简单理解为:当前的执行程序中已经包含上一代完整的链接库,如果在上一代可以成功运行,那么就相当于在新一代的情况下做用上一代的工具做上一代的事情。也没有什么大问题,可能性能差点。

  静态链接库的缺点

  1. 太占内存了
    对于每次调用静态链接库,都会把整个库放到可执行文件中。如果一个程序调用了很多个静态库,并且有很多个程序。那么对内存的耗费是极大的!而且不同程序中调用的可能是库的相同部分(术语叫公共代码),那这部分就会多次占用内存。

  其实动态链接库,静态链接库作为对立的存在。优缺点基本上是互补的。

  动态链接库的优点

  1. 对于内存空间大大节省
    由于动态性的特点,可执行文件中不包括库中函数的代码,就省了这部分的空间。

  2. 可扩展性更好
    如果发生版本更新的情况,肯定是要优先使用新版本(要不为啥有新版本,肯定性能更好)。对于调用静态链接库来说就需要重新进行编译,这样才能把新版本带入可执行程序中。但动态链接库由于主函数和库的相对独立性,在库中做修改不会影响到可执行程序。在程序运行时,再动态链接新版的库。不需要再次经历编译的过程。

  动态链接库的缺点

  1. 需要保护lib文件
    动态链接肯定有动态链接的方式,这个方式就是lib文件(下文会具体介绍)。如果lib文件丢失,可执行程序就无法在调用时找到对应的函数,进而造成程序运行失败。

  2. 运行时间较慢
    这个和上面静态链接库基本相对。在此不再赘述。

三、动态链接库的调用方式:

  动态链接库的调用方式分为两种:隐式调用和显式调用。其实两种方式最终的结果是相同的,但是编程的方式不太一样。

  再此之前先解释一个概念。上文提到了.lib文件,下面介绍一下在动态库中lib文件的作用

  lib文件中存储的其实是在动态库中各个函数的坐标。在可执行程序调用动态链接库的时候就可通过lib文件找到想要的函数位置,再去.dll文件中找到具体的函数。

  隐式调用:
    隐式调用就是使用lib文件的方式进行调用,对于隐式调用来说lib文件就是必须的!

  显式调用:
    显式调用其实就是不使用lib文件完成动态链接。这就要求在写可执行程序的时候就指明要去哪里动态链接。说一下显式调用的步骤(其实我也不懂,从百度下copy的)

  显式调用动态库步骤:

  1、创建一个函数指针,其指针数据类型要与调用的 DLL 引出函数相吻合。

  2、通过 Win32 API 函数LoadLibrary()显式的调用DLL,此函数返回DLL 的实例句柄。

  3、通过 Win32 API 函数GetProcAddress()获取要调用的DLL 的函数地址,把结果赋给自定义函数的指针类型。

  4、使用函数指针来调用 DLL 函数。

  5、最后调用完成后,通过 Win32 API 函数FreeLibrary()释放DLL 函数。

参考网址为:https://zhidao.baidu.com/question/941369803910889532.htmllink

  隐式调用和显式调用的区别?

    从对步骤的论述上看,清晰看出显式调用更为麻烦,对编程人员的要求更高。但努力是有回报的,显式调用更加灵活,可模拟多态(就是封装性比较好,调用灵活)的特性。

  注意:显示调用是可不使用lib文件,不是不可使用。

四、关于链接库的相关文件说明

Windows
  静态链接库文件:.lib
  动态链接库文件:.dll

Linux:
  静态链接库文件:.a
  动态链接库文件:.so——在Linux下动态链接库的命名规则为:lib+库名.so。例如:libcublas.so

  在windows下,静态链接库和动态链接库的隐式调用文件都是以.lib结尾,但里面的内容大不相同哦。

介绍两个Linux下关于动态链接库的命令:

ldd + 程序名  
举例:ldd main.c
作用:查看指定程序的动态链接库

nm -D + 动态链接库名字 
举例:nm -D libcublas.so
作用:输出该动态链接库内所有的函数名

  Linux下使用命令行调用库的时候分为三种:-I(大写的i)、-L(大写的l)、-l(小写的l)。对这三种不同的作用说明一下:

-I(大写的i)用于链接头文件(可曾想起include?-L(大写的l)用于链接到库搜索目录

-l(小写的l)用于链接到指定的动态库

  同时在Linux下使用时,动态链接库的搜索顺序有一个优先级的划分,再此也说明一下(序号代表优先级顺序,即1最高):

   1. 编译程序时加入-L/-l命令并指明路径

    例:g++ -o test -L. -llib -Wl,rpath=./ test.cpp

   2. 设置环境变量LD_LIBRARY_PATH

    例:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

   3. 设置 /etc/id.so.conf

    对于这个说明一下,因为这个是read only文件。在修改之前要设置一下,并且修改之后需要sudo执行一下。

   4. 把库放到系统默认路径中,即/usr/lib中

  以上对于优先级的内容参考博客:https://www.cnblogs.com/vanishfan/archive/2013/01/15/2861211.htmllink

最后分享两个学习过程中看到的相关博客:

动态链接库实例博客:https://blog.csdn.net/qq_33113661/article/details/88991909link

解释.h .lib .dll关系的博客:https://www.cnblogs.com/azbane/p/7364060.htmllink

由于作者水平有限,如有错误之处,请在下方评论区指正,谢谢!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值