DLL链接

QT DLL
http://blog.csdn.net/jiong_1988/article/details/7900593
http://qimo601.iteye.com/blog/1397936


静态链接库: .a .lib
里面的目标代码只能进行静态链接,称为“静态库”。
一个或者多个obj文件的打包,从obj文件生成lib的过程称为Archive,即合并到一起。


其实就是把原来的目标代码放在一起,链接程序根据每一份目标代码的符号表查找相应的符号(函数和变量的名字),找到的话就把该函数里面需要定位的进行定位,然后将整块函数代码放进可执行文件里,若是找不到需要的函数就报错退出。


1. 链接后产生的可执行文件包含了所有需要的目标代码,因此占用磁盘空间较大。
2. 如果有多个(调用相同库函数的)进程在内存中同时运行,内存中就存有多份相同的库函数代码,因此占用内存空间较多。




动态链接库: .so .dll
程序装载内存的时候才真正的把库函数代码链接进行确定它们的地址,并且就算有几个程序同时运行,内存也只存在一份函数代码。
经过特别处理的代码 —— “位置无关代码(Position independed Code .PIC)”。
动态链接库 (DLL) 是作为共享函数库的可执行文件。
优点:
1. 扩展了应用程序的特性
2. 有助于共享数据和资源, 有助于应用程序的本地化
3. 节省内存 (多个应用程序可同时访问内存中单个DLL副本的内容)
4. 简化软件项目的管理
5. 可以用多种编程语言来编写
6. 有助于解决平台差异


根据载入程序何时确定动态代码的逻辑地址,可以把动态装载分为两类。
1. 静态绑定(static binding)
使用静态绑定的程序一开始载入内存的时候,载入程序就会把程序所有调用到的动态代码的地址算出确定下来,这种方式使程序刚运行的初始化时间较长,不过一旦完成动态装载,程序的运行速度就很快。


2. 动态绑定(dynamic binding)
并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态绑定的程序。


导入库:lib后缀,动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。
有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
导入库仅包含加载DLL的代码和实现DLL函数调用的代码。在导入库中找到外部函数后,会通知链接器此函数的代码在DLL中。




有两种类型的链接:隐式链接和显式链接。
Implicit Linking(隐式连接)
又叫静态载入=静态绑定(static binding), 程序在连接时期即与dlls所对应的import libraries作静态连接,于是可执行文件中便对所有的dll函数都有一份重定位表格(relocation table)和待修正记录(fixup record)。当程序被windows载入器载入内存中时,载入器会自动修正所有的fixup records,而这个fixup records 就是记录DLL中所有输出资源的正确位置地址,经过这样的程序动态连接便自动产生。
优点
1、dll会在应用程序执行时载入,然后直接调用所有dll中提供的类或函数,不需要resolve或者GetProcAddress
2、处理简单,载入的方法有编译器负责处理,不需动脑筋
缺点
1、当所使用的dll不存在时,程序开始就会报dll无法找到的错误而使得程序无法运行
2、编译时需要加入import library
3、若调用的dll很多,载入应用程序的速度就会很慢
4、如修改DLL,必须用新的import lib去重新build app程序


Explicit Linking(显式连接)
又叫动态载入=动态绑定(dynamic binding),使用dll的可执行文件必须明确调用载入和御载dll的函数调用(Function Call),并且存取dll的输出函数。自行控制载入dll时机。用户端必须通过函数声明调用函数。
优点
1、dll只有需要时才载入内存中,这样可以更有效地使用存储空间
2、应用程序载入速度较隐式连接较快
3、编译时不需要额外的import library
4、可以让用户个清楚地知道dll的载入流程
5、即使不存在某些DLL,不到正式需要时也不会crash
缺点
1、处理麻烦,必须多写一点代码 (C++ Class显式连接麻烦)
   使用LoadLibrary这个Windows API来手动载入DLL,并使用GetProcessAddress来取得所需要使用的函数的函数指针,最后用FreeLibrary将DLL释放。


需要注意的显式链接的两个缺点:
     如果 DLL 具有 DllMain 入口点函数,则操作系统在调用 LoadLibrary 的线程上下文中调用此函数。 如果由于以前调用了 LoadLibrary 但没有相应地调用 FreeLibrary 函数而导致 DLL 已经附加到进程,则不会调用此入口点函数。 如果 DLL 使用 DllMain 函数为进程的每个线程执行初始化,显式链接会造成问题,因为调用 LoadLibrary(或 AfxLoadLibrary)时存在的线程将不会初始化。
     如果 DLL 将静态作用域数据声明为 __declspec(thread),则在显式链接时 DLL 会导致保护错误。 用 LoadLibrary 加载 DLL 后,每当代码引用此数据时 DLL 就会导致保护错误。 (静态作用域数据既包括全局静态项,也包括局部静态项。)因此,创建 DLL 时应避免使用线程本地存储区,或者应(在用户尝试动态加载时)告诉 DLL 用户潜在的缺陷。




大部分应用程序使用隐式链接,因为这是最易于使用的链接方法。有时也需要显式链接。
当一个可执行文件隐式的连接dll时,其他程序还可以显示地连接它。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值