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

news2024/11/19 5:53:28

文章目录

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

动态链接库和静态链接库

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

以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.coloradmin.cn/o/1302599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JDK多版本集成 Jacoco 配置指南

JDK多版本集成 Jacoco 配置指南 本篇相关 JDK 版本配置如下&#xff1a; JDK8 JDK11 JDK17 Jacoco 是什么 Jacoco 是一个用于Java程序的代码覆盖率报告工具。它通过动态分析&#xff08;在代码执行时收集数据&#xff09;来生成代码覆盖率报告文件。Jacoco 支持多种覆盖率标…

CSS新手入门笔记整理:元素类型相互转换

元素类型 块元素&#xff08;block&#xff09; 独占一行&#xff0c;排斥其他元素跟其位于同一行&#xff0c;包括块元素和行内元素。块元素内部可以容纳其他块元素和行内元素。可以定义 width&#xff0c;也可以定义 height。可以定义 4 个方向的 margin。 行内元素&#xf…

正运动ZDevelop软件使用流程

ZDevelop是正运动技术ZMoiton系列运动控制器的PC端程序开发调试与诊断软件&#xff0c;通过它用户能够很容易的对控制器进行程序编辑与配置&#xff0c;快速开发应用程序、实时诊断系统运行参数以及对运动控制器正在运行的程序进行实时调试&#xff0c;支持中英双语环境。 BAS…

川崎ZX-6R确定引进,636它真的来了,3C认证已过。

最新消息&#xff0c;兄弟们&#xff0c;你们期待已久的川崎ZX6R&#xff08;636&#xff09;基本已经确定引进了&#xff0c;官方的3C认证已经通过&#xff0c;那么从3C里面我们可以看到哪几个信息&#xff1f;产品代号ZX636J就是心心念念的ZX-6R了。 有些小伙伴不太清楚3C认…

MYsql第二次作业

目录 问题 解答 1. 2. 3. 4. 5. 6. 7.查看所有人的年龄 8. 9. 10 11 12.查询部门号为103或102的职工号&#xff0c;姓名&#xff0c;政治面貌 13. 14 15 16 17. 问题 解答 1. 2. 3. 4. 5. 6. 7.查看所有人的年龄 8. 9. 10 11 12.查询部门号为103或102的职…

基于PaddleOCR银行卡识别实现(四)之uni-app离线插件

目的 在前三篇文章中完成了银行卡识别整个模型训练等工作&#xff0c;通过了解PaddleOCR的端侧部署&#xff0c;我们也可以将银行卡号检测模型和识别模型移植到手机中&#xff0c;做成一款uni-app手机端离线银行卡号识别的应用。 准备工作 为了不占用过多篇幅&#xff0c;这…

字符统计[c]

#include<stdio.h> #include<string.h> int main() {int a,b,c;abc0;char s[100];int i0;while(1){i;scanf("%c",&s[i]);if(s[i]?)break;}for(int k1;k<i;k){if(s[k]>48&&s[k]<57){a;//数字}else if((s[k]>65&&s[k]<…

1. mycat入门

1、mycat介绍 Mycat 是一个开源的分布式数据库系统&#xff0c;但是由于真正的数据库需要存储引擎&#xff0c;而 Mycat 并没有存 储引擎&#xff0c;所以并不是完全意义的分布式数据库系统。MyCat是目前最流行的基于Java语言编写的数据库中间件&#xff0c;也可以理解为是数据…

I/O设备模型

I/O设备模型 绝大部分的嵌入式系统都包括一些I/O&#xff08;Input/Outut&#xff0c;输入/输出&#xff09;设备&#xff0c;例如仪器上的数据显示屏、工业设备上的串口通信、数据采集设备上用于保存数据的Flash或SD卡&#xff0c;以及网络设备的以太网接口等。 I/O设备模型…

视频剪辑:视频创意制作,背景图片融合视频制作画中画效果

随着社交媒体的兴起&#xff0c;视频制作不再仅仅是专业人士的专利。每个人都可以通过一些技巧&#xff0c;创作出独特而富有吸引力的视频内容。视频剪辑是一种非常重要的技术&#xff0c;它能让视频从平淡无奇变为生动有趣。背景图片融合视频制作画中画效果&#xff0c;也能增…

App自动化测试之Appium 环境搭建保姆级教程(全网最全)

前言 APP自动化测试运行环境比较复杂&#xff0c;稍微不注意安装就会失败。我见过不少朋友&#xff0c;装了1个星期&#xff0c;Appium 的运行环境还没有搭好的。 搭建环境本身不是一个有难度的工作&#xff0c;但是 Appium 安装过程中确实存在不少隐藏的比较深的坑&#xff…

fragment常用知识点

fragment基本使用 摘自官网的代码示例 class ExampleActivity : AppCompatActivity(R.layout.example_activity) {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 注意这里有判断&#xff0c;当saveInstanceState为空时再创建。…

git提交代码报错Git: husky > pre-commit

目录 git提交代码报错原因解决方法&#xff08;三种&#xff09;1、第一种2、第二种3、第三种 git提交代码报错原因 这个问题是因为当你在终端输入git commit -m “XXX”,提交代码的时候,pre-commit(客户端)钩子&#xff0c;它会在Git键入提交信息前运行做代码风格检查。如果代…

53 代码审计-TP5框架及无框架变量覆盖反序列化

目录 演示案例:Metinfo-无框架-变量覆盖-自动审计或搜索phpmyadmin-无框架-反序列化-自动审计或搜索Thinkphp5-有框架-搭建使用入口访问调试SQL等 演示案例: Metinfo-无框架-变量覆盖-自动审计或搜索 变量覆盖会直接覆盖原始变量&#xff0c;来形成新的变量值 搜索关键字或者…

智慧社区前景无限,科技引领未来发展

社区是城镇化发展的标志&#xff0c;作为人类现代社会的生活的基本圈子&#xff0c;是人类生活离不开的地方&#xff0c;社区人口密度大、车辆多&#xff0c;管理无序&#xff0c;社区的膨胀式发展多多少少带来一定的管理上的缺失。社区作为智慧城市建设的重要一环&#xff0c;…

zedbox 实现配置 yolov5

Stereolabs 的 ZED Box 是一款由 NVIDIA Jetson™ 提供支持的紧凑型网关&#xff0c;用于在移动和现场情况下挑战 AIoT&#xff08;物联网&#xff09;。它旨在将空间感知和理解带到边缘&#xff0c;并聚合、处理和分析来自 3D 传感器和设备的数据。 相关内容 1.win10下 cud…

A-23 P离子交换树脂:高效去除无机有机污染物的新选择

在当今水处理行业中&#xff0c;高效、环保的离子交换树脂备受关注。本文将为您介绍一款具有卓越性能的碱性季胺基阴离子交换树脂——Tulsion A-23 P。通过分析其特性和应用&#xff0c;展示其在水处理领域的优势。 一、Tulsion A-23 P离子交换树脂的特性 物理化学稳定性&#…

Connection refused: no further information

解决目录 一、报错信息二、解决方法 一、报错信息 二、解决方法 1、报错原因是开启了代理&#xff0c;像AS是绝对不能开代理的。 2、设置为No proxy&#xff0c;然后Apply再选择OK&#xff0c;重新同步。 要远离消耗你的人和事&#xff0c;不要花费任何情绪或者精力在他们身…

【排序算法】快速排序

一&#xff1a;基本概念 1.1 介绍 快速排序由C. A. R. Hoare在1962年提出&#xff0c;它是一种基于二叉树结构的交换排序算法&#xff0c;它采用了一种分治的策略&#xff0c;通常称其为分治法。该方法的基本思想是&#xff1a;先从数列中取出一个数作为基准数&#xff0c;然…

【MySQL系列】Centos安装MySQL

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…