静态链接库与动态链接库

这篇具有很好参考价值的文章主要介绍了静态链接库与动态链接库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、从源程序到可执行文件

由于计算机无法直接理解和执行高级语言(C、C++、Java)程序,需要将高级语言程序转换为机器语言程序(机器语言是用二进制代码表示的、计算机唯一可以直接识别和执行的一种机器指令的集合),通常把这种转换过程叫做翻译

在C/C++中,整个翻译过程可以分为四步:

  • 预处理阶段预处理器对源程序进行 #include 头文件展开、#define 宏替换、#ifdef 条件编译以及行号和文件标识的添加等预处理操作,输出结果是一个以.i为扩展名的源文件。通过 g++ -E main.cpp > main.i 命令可以生成预处理信息并将预处理信息重定向到指定文件中。
  • 编译阶段编译器对预处理后的源程序进行词法分析、句法分析等编译操作,生成一个以.s为扩展名汇编语言源程序。汇编语言源程序中的每条语句都以一种文本格式描述了一条低级机器语言指令。通过 g++ -S main.cpp -o main.s 命令即可编译生成汇编文件。
  • 汇编阶段汇编器将汇编语言源程序翻译成机器语言指令,并把这些指令打包成一个以.o为扩展名的可重定位目标文件,它是一种二进制文件,因此用文本编辑器打开会显示乱码。通过 g++ -c main.cpp -o main.o 命令即可汇编生成可重定位目标文件。
  • 链接阶段链接器将多个可重定位目标文件链接库合并为一个可执行目标文件,或简称可执行文件,最终生成的可执行文件被保存在磁盘上。通过 g++ main.cpp -o main 命令即可实现从源程序到可执行文件的翻译过程。

静态链接库与动态链接库


二、编译、链接和装入

从操作系统程序执行的角度来看,一个程序想要放在内存中执行,除了上面的翻译过程(预处理、编译、汇编、链接),还需要对程序进行装入操作。

具体来说,编译是由编译程序对用户源程序进行编译,形成若干目标模块的过程,这些目标模块中的地址均为伪逻辑地址,即 0-100-100-10链接则是由链接程序将一组目标模块及所需库函数进行链接,形成一个完整的装入模块的过程,这个装入模块中的地址为逻辑地址,即 0 - 32。而装入则是由装入程序将装入模块装入内存,装入后形成的是物理地址,即 1000-1032

链接方式主要分为以下三种:

  • 静态链接:装入前链接成一个完整的装入模块,以后不再拆开。
  • 装入时动态链接:运行前装入内存时边装入边链接,便于对目标模块的修改、更新与共享。
  • 运行时动态链接:运行时需要目标模块才装入并链接,加快了程序装入,节省了内存空间。

装入方式也有三种:

  • 绝对装入:在单道程序环境下,编译时直接生成物理地址目标代码,直接按此地址装入。仅适用于单道程序,且要求程序员对内存极为熟悉,但实际上编程一般使用符号地址。
  • 可重定位装入:通过静态重定位在装入时将地址变换一次性完成,一次性装入。装入时必须分配固定大小全部空间,内存不足无法装入,不支持程序浮动。
  • 动态运行时装入:装入时不进行地址变换,直到运行时再借助重定位寄存器进行动态重定位。装入部分代码即可运行,可以分散存储,支持程序浮动,便于共享。

三、静态链接库与动态链接库

装入时动态链接和运行时动态链接均为动态链接,都是将部分链接操作推迟到程序执行时才进行,而动态链接一般需要使用动态链接库。而静态链接则是在生成可执行文件之前完成所有链接操作,使用的库文件被称作静态链接库

静态函数库一般命名为 libxxx.axxx.lib静态函数库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容,但升级时如果函数库更新则需要重新编译

动态函数库一般命名为 libxxx.soxxx.dll。与静态函数库被整个编译到程序中不同,动态函数库只有当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用,也就是说可执行文件无法单独运行,这样方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件

静态库和动态库最本质的区别就是加载的时机,静态库在编译阶段就会加载到可执行文件中,而动态库会在执行阶段加载到可执行文件中


四、静态链接库与动态链接库的制作与使用

lib_fun.h:

void func(int &num);

lib_fun.cpp:

#include "lib_fun.h"

void func(int &num) {
    num++;
}

main.cpp:

#include <iostream>
#include "lib_fun.h"

using namespace std;

int main() {
    int x = 0;

    func(x);
    cout << x << endl;

    return 0;
}

1.静态库的制作及使用

静态库的制作命令为:

g++ -c xxx.cpp -o xxx.o # 将目标源文件xxx.c编译成目标文件xxx.o
ar -rcs libxxx.a xxx.o # 使用ar工具制作静态库libxxx.a

首先我们使用 tree 命令查看一下当前目录结构,其中user目录模拟用户,lib目录模拟库。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo$ tree
.
├── lib
│   ├── lib_fun.cpp
│   └── lib_fun.h
└── user
    ├── lib_fun.h
    └── main.cpp

2 directories, 4 files
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo$ 

我们在user目录下先编译一下main.cpp看一下效果,可以看到 func(int&) 声明了但没有定义,因为如果没有找到声明会直接报 was not declared in this scope

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo$ cd user/
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ g++ main.cpp -o main
/usr/bin/ld: /tmp/ccnh1mTY.o: in function `main':
main.cpp:(.text+0x2a): undefined reference to `func(int&)'
collect2: error: ld returned 1 exit status
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ 

然后我们回到lib目录制作静态库,静态库的命名格式为 libxxx.a,并将制作好的静态库拷贝到user目录下cd。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ cd ../lib/
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ g++ -c lib_fun.cpp -o lib_fun.o
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ ar -rcs libfun.a lib_fun.o
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ cp libfun.a ../user/
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ tree ../
../
├── lib
│   ├── libfun.a
│   ├── lib_fun.cpp
│   ├── lib_fun.h
│   └── lib_fun.o
└── user
    ├── libfun.a
    ├── lib_fun.h
    └── main.cpp

2 directories, 7 files
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ 

我们转到user目录下,重新进行编译,编译命令中的 -l 后面跟的是动态库的名字,即 libxxx.a 中的 xxx-L 后面跟的是静态链接库 libxxx.a 的存放位置,这里就在当前文件夹。可以看到,在链接了静态库之后就可以正常执行了。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ g++ main.cpp -l fun -L ./ -o main
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ ./main 
1
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ 

2.动态库的制作及使用

动态库的制作命令为:

g++ -shared -fPIC -o libxxx.so xxx.cpp # 制作动态库libxxx.so

首先我们依然是使用 tree 命令查看一下当前目录结构。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo$ tree
.
├── lib
│   ├── lib_fun.cpp
│   └── lib_fun.h
└── user
    ├── lib_fun.h
    └── main.cpp

2 directories, 4 files
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo$ 

同样的,在lib目录下制作动态库,并将其拷贝到user目录下。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ g++ -shared -fPIC -o libfun.so lib_fun.cpp
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ cp libfun.so ../user/
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ 

我们转到user目录下,重新进行编译,编译命令中的 ./libfun.so 即为动态库的存放路径。可以看到,在链接了动态库之后就可以正常执行了。

atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/lib$ cd ../user/
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ g++ main.cpp ./libfun.so -o main
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ ./main 
1
atreus@iZwz9fsfltolu74amg1v0rZ:~/Code/lib_demo/user$ 

静态链接库与动态链接库文章来源地址https://www.toymoban.com/news/detail-444501.html

到了这里,关于静态链接库与动态链接库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于STM32智能窗帘控制系统仿真设计(含源程序+proteus仿真+讲解视频)

    # 基于STM32智能窗帘设计(含源程序+proteus仿真) 仿真:proteus8.11 程序编译器:keil 5 编程语言:C语言 编号C0007 资料下载链接 基于STM32的简易智能窗帘控制系统仿真设计 实现功能: 有手动,自动两种模式 自动模式下,滑动变阻器模拟光照传感器,通过stm32检测与阈值比较 低于

    2024年02月13日
    浏览(48)
  • 基于单片机压力传感器MPX4115检测-报警系统-proteus仿真-源程序

    一、系统方案 本设计采用52单片机作为主控器,液晶1602显示,MPX4115检测压力,按键设置报警,LED报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 /******************************************************************* 液晶初始化 ******************************************

    2024年02月09日
    浏览(51)
  • 关于项目移植过程中,如何在不修改java源程序的情况下,如何适应新环境下的mysql

    在我们将这个自己电脑里面写好的web项目部署到这个我们自己的云服务器之前,我们已经部署好了这个相应的环境,jdk,tomcat ,mysql ,如果我们只是将自己的web项目部署到这个tomcat下面的话,这个数据库很可能是连接不是上的, 原因是因为这个原来项目中的数据源的配置信息或

    2024年02月02日
    浏览(41)
  • 51单片机步进电机全套资料(启停+正反转+加减速+显示速度+中断)【源程序+流程图+接线图+视频+答辩报告】综合设计首选

      一、设计目标     设计程序实现按键控制步进电机启动、停机、正反转、加减速、转速及转向显示。 二、主要功能     功能1:步进电机的启动、重启、停机;     功能2:步进电机正反装;     功能3:静态数码管显示速度等级;     功能4:步进电机的加减速; 三、硬

    2024年02月12日
    浏览(43)
  • 动态库与静态库

    动态库(Dynamic Library)和静态库(Static Library)是软件开发中常用的两种库文件形式。 动态库:是一组共享的目标代码文件,它们在运行时动态链接到应用程序中。动态库在系统中独立存在,可以被多个应用程序共享。当应用程序运行时,操作系统会加载动态库,并在需要时

    2024年02月08日
    浏览(42)
  • 在程序中链接静态库 和 动态库

    mkdir shareLib mkdir staticLib 把这篇文章  生成的libcalc.so放入shareLib、libcalc.a放入staticLib 一、在程序中链接静态库  CMakeLists.txt CMakeLists.txt   (也可以写成这样)  二、在程序中链接动态库 CMakeLists.txt CMakeLists.txt   (也可以写成这样)  知识点:

    2024年01月17日
    浏览(54)
  • 【Linux】静态库与动态库

    前言 对于C/C++的学习者,我们经常听到C/C++的标准库,我们也经常使用它们,但是我们在使用的时候经常只包含一下头文件,然后就使用了,我们从来没有认真的研究过C/C++的标准库,而且C/C++的头文件中只有声明并没有声明的内容的具体实现,为什么我们只包含头文件就能使

    2024年02月05日
    浏览(53)
  • 【Linux】动态库与静态库

    目录 一、前言 二、静态库与动态库 三、生成静态库 1、生成原理 2、完整过程 3、总结 四、生成动态库 1、环境变量 2、建立软链接 3、配置文件 五、动态库的加载 1、动态库加载的过程 2、动态库地址的理解 3、补充内容  关于动态库与静态库的一小部分前置内容,我曾在文

    2024年02月01日
    浏览(50)
  • 【Linux:动态库与静态库】

    静态库( .a ):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 动态库( .so ):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表

    2024年02月06日
    浏览(41)
  • Linux中的动态库与静态库

    软链接 当我们不在本地路径下运行时,运行目标二进制文件一般要写明该程序路径. 但是这样运行对于路径较为复杂的程序极为耗费时间,为了简便操作,我们可以将该可执行程序的路径设置为软链接.此时的软链接一般也可认为是windows可执行程序的快捷方式. 创建软链接命令如下

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包