静态链接库和动态链接库(隐式载入显式载入)

文章目录

  • 动态链接库和静态链接库
    • 什么是链接库?
    • 静态链接库
    • 动态链接库
    • 动态链接库的俩种链接方式
      • 加载时动态链接
      • 运行时动态链接

动态链接库和静态链接库

动态链接库和静态链接库都是共享代码的方法,只是二者略有区别。

以C/C++为例,一个可执行文件的生成主要包括预编译、编译、汇编和链接。而静态链接和动态链接就是 在链接阶段的俩种处理。
在这里插入图片描述

什么是链接库?

关于代码复用,有些文件专门用于存储可以重复使用的代码块,例如功能实用的函数或者类,我们通常将它们称为库文件,简称“库”(Library)。将这种库文件进行打包编译后得到二进制文件就是链接库。

链接库是一个不能独立运行的二进制文件,它必须经过其他程序调用,才可以载入内存中。

根据链接方式的不同,可以分为静态链接库动态链接库

静态链接库

所谓静态链接,就是在程序执行前,将所有目标文件同静态链接库一起组织成可执行文件,这样生成的可执行文件可以独立运行

采用静态链接库的方式共享代码有一个明显的缺点,那就是文件的体积会很大,因为可执行文件包含了所有目标文件和静态链接库的数据。这样容易造成内存空间的浪费。同时,不利用代码的模块化:如果有某个模块需要更新,整个程序都需要重新连接才能运行。

若是有多个程序调用相同函数,内存中就会存在这个函数的多个拷贝。

动态链接库

动态链接是相对静态链接而言的,动态链接所调用的代码并没有被打包到可执行文件中,被拷贝的往往只是某些函数的描述信息(如重定位信息),只有当程序执行的过程中,需要调用到动态库中的函数式,动态链接库中的函数才会被载入内存中。

一般情况下,一个程序如果使用了动态链接库,系统会保证内存中只有一份DLL的复制品。

动态链接库可以随可执行文件一同载入内存,也可以在可执行文件运行过程中载入,即可执行文件什么时候需要,动态链接库才会载入内存。

采用动态链接库方便程序的更新,当程序的某个模块更新后,只需要将旧的模块替换掉,程序运行时会自动将所有模板载入内存并动态地链接在一起。

但是动态链接库也有一定的缺点,静态链接生成的可执行文件能够在其他同类操作系统上直接运行。但是如果是动态链接生成的文件,在移植到其他操作系统上后,需要连同该可执行文件所调用到的DLL文件一并拷贝过去,不然不能保证程序的正常运行。

动态链接库的俩种链接方式

动态链接实际上还有俩种不同的连接方式:加载时动态链接和运行时动态链接(隐式加载显式加载

加载时动态链接

在加载时动态链接中,应用程序像本地函数一样显式调用导出的 DLL 函数。要使用加载时动态链接,请在编译和链接应用程序时提供头文件 (.h) 和导入库 (.lib) 文件。执行此操作时,链接器将为系统提供加载 DLL 所需的信息,并在加载时解析导出的 DLL 函数位置。

使用加载时动态链接,同静态链接有一个相同的缺点,那就是如果程序的体积稍大,程序开始时加载的时间就会过长。

加载时动态链接和静态链接的区别:

  • 链接的时机:加载时动态链接是在程序加载时程序才会将动态库载入到内存中,而静态链接则是在编译的时候就已经将静态库的代码和数据嵌入到可执行文件中了。

正如上面所说的,使用加载时动态链接,需要提供头文件 (.h) 和导入库 (.lib) 文件。可以直接在源码中引入.lib文件。

例如:

#pragma comment(lib, "dllDemo.lib")

为了更好的模块化设计,也可以将lib中所要用到函数声明放在头文件中。

例如:

//dllDemo.h
#ifndef _DLLDEMO_H
#DEFINE _DLLDEMO_H#pragma comment(lib,"dllDemo.lib")
_declspec(dllexport) int add(int, int);
_declspec(dllexport) int sub(int, int);#endif

之后的主程序中记得

#include "dllDemo.h"

上述代码还用了_declspec(dllimport) 标识符声明函数来自动态链接库。

运行时动态链接

在运行时动态链接中,应用程序调用LoadLibrary 函数或LoadLibraryEx 函数在运行时加载DLL。 DLL成功加载后,可以使用GetProcAddress函数获取要调用的导出DLL函数的地址。当您使用运行时动态链接时,不需要导入库文件。

LoadLibrary 函数的作用是将指定的模块加载到调用进程的地址空间中。

函数定义:

HMODULE LoadLibraryA([in] LPCSTR lpLibFileName //模块的名称。这可以是库模块(.dll 文件)也可以是可执行模块(.exe文件)
);

如果调用成功,将会返回该模块的句柄。

当得到该模块的句柄后,可以使用GetProcAddress函数,它从指定的动态链接库 (DLL) 检索导出函数(也称为过程)或变量的地址。

函数原型:

FARPROC GetProcAddress([in] HMODULE hModule, //该模块的句柄[in] LPCSTR  lpProcName  //函数或变量的名称
);

如果调用成功,则返回导出函数或变量的地址。

示例:

#include <windows.h>int main() {// 加载动态链接库HMODULE hLibrary = LoadLibrary("example.dll");if (hLibrary != NULL) {// 获取函数地址FARPROC functionAddress = GetProcAddress(hLibrary, "exampleFunction");if (functionAddress != NULL) {// 调用动态链接库中的函数typedef void (*FunctionType)();FunctionType myFunction = (FunctionType)functionAddress;myFunction();}// 卸载动态链接库FreeLibrary(hLibrary);}return 0;
}

以上关于运行时动态链接的实例是基于Windows的,如果是在linux上使用运行时动态链接,则需要通过使用 dlopendlsym以及 dlclose函数。

实例:

#include <dlfcn.h>int main() {// 加载动态链接库void* libraryHandle = dlopen("libexample.so", RTLD_LAZY);if (libraryHandle != NULL) {// 获取函数地址void (*myFunction)() = (void (*)())dlsym(libraryHandle, "exampleFunction");if (myFunction != NULL) {// 调用动态链接库中的函数myFunction();}// 卸载动态链接库dlclose(libraryHandle);}return 0;
}
参考
https://learn.microsoft.com/en-us/troubleshoot/windows-client/deployment/dynamic-link-library
https://c.biancheng.net/dll/what_is_library.html
https://blog.csdn.net/fuzhongmin05/article/details/54616520
https://blog.csdn.net/u010154760/article/details/45689899?spm=1001.2014.3001.5502

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/267560.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DevEco Studio 生成HPK文件

DevEco Studio 生成HPK文件 一、安装环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、生成HPK文件 生成的HPK文件存放在entry文件夹下。下图是未生成HPK的样式。 生成HPK&#xff1a;菜单Build->Build Hap(s)/APP(s)->Build Hap(s)…

手动搭建koa+ts项目框架(日志篇)

文章目录 前言一、安装koa-logger二、引入koa-logger并使用总结如有启发&#xff0c;可点赞收藏哟~ 前言 本文基于手动搭建koats项目框架&#xff08;路由篇&#xff09;新增日志记录 一、安装koa-logger npm i -S koa-onerror and npm i -D types/koa-logger二、引入koa-lo…

Java EE 多线程之 CAS

文章目录 1. 什么是 CAS2. CAS 有那些应用2.1 实现原子类2.2 实现自旋锁2.3 ABA 问题2.3.1 ABA 问题的解决方案 1. 什么是 CAS CAS&#xff1a;全称Compare and swap 假如有一个内存 M 有两个寄存器 A B CAS(M, A, B) 如果 M 和 A 的值相同的话&#xff0c;就把 M 和 B 里的值…

和鲸科技携手深圳数据交易所,“数据+数据开发者生态”赋能人工智能产业发展

信息化时代&#xff0c;数据驱动决策的重要性日益凸显。通过利用数据可以深入了解市场需求、客户行为、竞争态势等关键信息&#xff0c;从而制定更为有效的战略和决策。围绕推动数据要素产业发展&#xff0c;近日&#xff0c;深圳数据交易所&#xff08;以下简称“深数所”&…

网络安全——Iptables防DDoS攻击实验

一、实验目的要求&#xff1a; 二、实验设备与环境&#xff1a; 三、实验原理&#xff1a; 四、实验步骤&#xff1a; 五、实验现象、结果记录及整理&#xff1a; 六、分析讨论与思考题解答&#xff1a; 一、实验目的要求&#xff1a; 1、掌握常见DDoS攻击SYN Flood的攻击…

PyTorch张量:内存布局

你可能对 torch 上的某些函数感到困惑&#xff0c;它们执行相同的操作但名称不同。 例如&#xff1a; reshape()、view()、permute()、transpose() 等。 这些函数的做法真的不同吗&#xff1f; 不&#xff01; 但为了理解它&#xff0c;我们首先需要了解一下张量在 pytorch 中…

scala集合_数组_元组_映射_列表

数组元组映射列表 1.11 集合&#xff08;scala.collection&#xff09; 集合是一种用来存储各种对象和数据的容器。Scala 集合分为可变的和不可变的集合。 1. 不可变集合可以安全的并发访问。 2. 可变集合可以在适当的地方被更新或扩展。这意味着你可以修改&#xff0c;添加…

二叉树--基础OJ

1.对称二叉树 题目链接&#xff1a;101. 对称二叉树 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; 我们可以用递归的方法去做&#xff1a; 如果两个树互为镜像&#xff08;1.根节点的值相同&#xff0c;2.左子树的值与右子树的值对称&#xff09;则为对称二叉树&a…

专栏十五:omicverse在单细胞分析中的实际使用体验和小改动

写一些自己的理解吧,一些小步骤,正在更新中。。。 安装 原作者写的很清楚了 大部分直接抄 个别地方:去选择下载适合自己的pytorch版本PyTorch, 比如我的是cuda12,下载命令实际是 pip3 install torch torchvision torchaudio 查看cuda版本命令 nvidia-smi 当然还有个命…

04-Nacos中负载均衡规则的配置

负载均衡规则 同集群优先 默认的ZoneAvoidanceRule实现并不能根据同集群优先的规则来实现负载均衡,Nacos中提供了一个实现叫NacosRule可以优先从同集群中挑选服务实例 当服务消费者在本地集群找不到服务提供者时也会去其他集群中寻找,但此时会在服务消费者的控制台报警告 第…

BMP转PNG工具BMP2PNG

自己写的一个BMP转PNG工具BMP2PNG 写这个工具是因为要使用传奇的部分素材在COCOS2DX使用&#xff0c; 但是COCOS2DX不支持BMP 如果直接将BMP转换到PNG的话&#xff0c;网上找到的工具都不支持透明色转换。难道要用PS一个一个抠图吗&#xff1f;要累死 所以写了这个工具。一些古…

《昆虫记》带我进入了一个昆虫的新世界。

《昆虫记》带我进入了一个昆虫的新世界。 《昆虫记》的作者是法国作家亨利.法布尔&#xff0c;他是法国著名的文学家&#xff0c;昆虫学家&#xff0c;科普作家。被世人称为“科学界的诗人”&#xff0c;“昆虫世界的荷马”&#xff0c;“昆虫世界的维吉尔”&#xff0c;他从小…