【Linux】动/静态库的创建和使用

目录

一、动/静态库的概念回顾:

二、动态库与静态库的区别:

三、静态库的创建与使用:

1、Linux静态库命名规则:

2、静态库的创建和使用:

四、动态库的创建与使用:

1、Linux动态库命名规则:

2、动态库的创建和使用:


一、动/静态库的概念回顾:

        从上一章节(基础I/O)中我们讲到,库其实就是已经写好的、成熟的、可以直接使用的代码,库里面封装了数据和函数,可以直接提供给用户进行调用。

而所谓的静态、动态是指在链接阶段如何处理库,链接成可执行文件。

编译过程:

二、动态库与静态库的区别:

静态库:

        静态库在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中(通俗点就是静态库在编译的链接阶段与目标文件一起打包生成可执行文件,成为可执行文件的一部分)。所以当多个应用程序同时引用一个静态库函数时就会在内存中调用函数的多个副本,大大增加可执行文件的体积,其优点是节省编译时间

动态库:

        动态库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被加载和链接。所以被调函数在内存中只有一个副本、可以实现进程之间资源的共享,且动态库可以在程序运行期间释放动态库所占用的内存。

        动态链接所调用的函数代码并不会拷贝到可执行文件中,也就是说可执行文件与动态库是分开的,只会在可执行文件中加入所调用函数的描述信息,当程序装载进内存中运行时,在OS的管理下会在程序与对应的动态库之间建立链接关系,当要执行所调用动态库的函数时,会根据链接产生重定位信息,然后去执行执行动态库中对应的函数。

三、静态库的创建与使用:

1、Linux静态库命名规则:

Linux的静态库的命名规范为:"lib[xxx].a"

lib为前缀,中间的xxx为这个静态库的名字,.a为拓展名,例如一个名为test的静态库为:libtest.a

2、静态库的创建和使用:

前面说到:静态库是在链接阶段将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。我们可以试想一下静态库会与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。

下面用一段简单的代码编译成静态库:

函数声明: add.h
int add(int x, int y);


函数定义: add.cpp
int add(int x, int y)
{
    return x + y;
}

Linux下使用ar工具、Windows下vs使用lib.exe,将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索。

一般创建静态库的流程如下:

通过上面的流程图可以看到,我们要先把代码文件编译成目标文件.o

g++ -c add.cpp

然后通过ar工具将目标文件打包成.a静态库文件(将add.o打包成libadd.a)

ar -crv libadd.a add.o

静态库的使用:

这里我们写一段使用库中函数的代码用来测试:

Linux下使用静态库一般为:

g++ Test.cpp -L ./ -l add

选项:

-L:表示要连接的库所在目录

-l:指定链接时所需要的库,去掉前缀lib和后缀,如上就是libadd.a去掉前后缀

此时我们删掉静态库可以发现:程序还是一样能正常运行,因为静态库已经成为这个可执行文件的一部分了,不需要依赖外界了(如下图

四、动态库的创建与使用:

1、Linux动态库命名规则:

Linux的动态库的命名规范为:"lib[xxx].so"

lib为前缀,中间的xxx为此动态库的名字,so为拓展名,例如一个名为test的动态库为:libtest.so

2、动态库的创建和使用:

前面说到:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。所以动态库只需要在内存中只存在一份拷贝即可,就能有效避免静态库浪费空间的问题,且对程序进行更新也只需要更新动态库,增量更新即可。

针对于实际库文件,每个共享库都有个特殊的名字"soname"。在程序启动后,程序会通过这个名字来告诉动态加载器该载入哪个共享库。

在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件 (lib+soname+.so)

创建动态库文件:这里我直接复用上面的代码

函数声明: add.h
int add(int x, int y);


函数定义: add.cpp
int add(int x, int y)
{
    return x + y;
}

生成动态库的命令为:g++ -fPIC -shared -o libadd.so add.cpp

选项:

-fPIC:创建与地址无关的编译程序(pic:position independent code),实现在多个应用程序间进行共享。

-shared:指定生成动态链接库。(生成.o文件)

-o:重命名,将打包出的库文件命名成libadd.so     

其实将整条命令拆分一下就是: 

g++ -fPIC -c add.cpp                            (生成.o文件)

g++  -shared -o libadd.so add.o         (生成.so库) 

注意下面这张图的a.out并不是动态库生成的,是上面静态库生成的。

动态库的使用:(Test.cpp代码还是和上面一样)

g++ Test.cpp -L ./ -l add    (引用动态库编译成可执行文件跟静态库的方式一样)

但是此时我们运行生成的可执行文件会发现这样子会报错!!!

这是因为编译器只会去库目录和环境变量中找动态库,Linux环境下的库文件一般都放在 /lib 或者 /usr/lib 目录下,所以我们得要让程序能找到动态库。

解决方法:

1、将生成的动态库拷贝到 /usr/lib 或者 /lib 目录下

(这种方法虽然简单直接,但是不推荐用这种方法,因为这会污染系统的库源)

2、修改环境变量 LD_LIBRARY_PATH

(环境变量 LD_LIBRARY_PATH是动态库的搜索路径,一般情况下为空,可执行文件运行时,会去这个环境变量中搜索动态库路径,但是注意:新建终端或者重启就会失效

3、建立软链接:

(直接在liblib64目录下建立一个指向这个动态库的一个软链接,推荐这种用法

(对于32位程序一般会链接到 /usr/lib 中的库。而64位程序则会链接到 /usr/lib64 中的库。但也有例外情况,例如:如果64位系统上的某个64位程序需要向后兼容32位库,它可能仍然会链接到 /usr/lib 中的库。)

补充:可以通过ldd 命令可以查看当前执行文件所链接的动态库

如果将对应需要的动态库删除的话那这里(红色框处)就会显示找不到库,自然程序也就无法运行了

如下:如果删除动态库,程序就会无法运行:

动态库更新:

更新时只需更新动态库即可,就不需要连同使用库的应用程序一起进行编译了,如下:更改了+的逻辑变成-,只需对动态库进行重新编译就可以实现程序更新了:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mac环境 aab包转apks,并安装apks

一、下载下载bundletool工具 Releases google/bundletool GitHub 二、将下载bundletool.jar包、aab、keystore文件全部放到同一个目录下 例如我全部放到download目录下 转换命令行: java -jar bundletool-all-1.16.0.jar build-apks --modeuniversal --bundle…

「全新升级,性能更强大——ONLYOFFICE 桌面编辑器 8.1 深度评测」

文章目录 一、背景二、界面设计与用户体验三、主要新功能亮点3.1 高效协作处理3.2 共同编辑,毫无压力3.3 批注与提及3.4 追踪更改3.5 比较与合并3.6 管理版本历史 四、性能表现4.1 集成 AI 工具4.2 插件强化 五、用户反馈与使用案例 一、背景 Ascensio System SIA -…

finalize——释放内存

重写 没写的话就按照定义的方法,object的默认方法 system.gc会主动调用垃圾回收器,不会使用finalize方法。需求不大 对于用debug怎么进入jdk源码,ararry.sort的源码进入

OpenAI: 禁止在不支持的地区使用其 API

OpenAI 给开发者发邮件表示,禁止其 API 用于不被允许的地区,否则 7 月 9 日将面临封杀。 本次封杀似乎不区分 IP ,而是直接按照地理位置。

Centos+Jenkins+Maven+Git 将生成的JAR部署到远程服务器上

1、登录 没有安装的参考下面的安装步骤先安装: Jenkins安装手册 输入账号、密码登录系统。 2、新建任务 2.1 创建页面 1,“输入一个任务名称”; 2,任务类型点击“构建一个maven项目”; 3,点击“确定”,此时,构建任务创建完成。 2.2 General 1、描述:输入要部署…

Kotlin设计模式:代理模式详解

Kotlin设计模式:代理模式详解 在软件开发中,设计模式是解决常见问题的一种优雅方法。本文将介绍Kotlin中的代理模式(Proxy Pattern),其应用场景,以及如何通过实例代码实现这一模式。 代理模式的目的 代理…

【软考高项】- 2024.05月成绩查询

查询地址:全国计算机技术与软件专业技术资格(水平)考试 考试批次:2024.05.26 第二批(论文:成本管理) 我的分数: 结论:未通过本次考试,2025.05 继续努力&…

判断对象是否为空的多种方式

判断对象是否为空 网上也有许多方法,这里来整理一下 一、Object.keys(obj) ES6 写法: const data {}; const arr Object.keys(data); console.log(arr.length); // 0二、JSON.stringify() const obj {}; const arr JSON.stringify(obj); console.…

基本工资8000,三班倒轮班,有点辛苦,技术含量高,但越老越吃香的工作工资待遇分享...

技术员的逆袭:数控技术员的职场升级攻略 引言 在职场这片星辰大海中,有一群默默耕耘的技术员,他们用双手和智慧,雕刻着工业的明天。数控技术员,一个听起来就充满机械感和科技感的职业,他们的故事&#xff0…

05-java基础——循环习题

循环的选择:知道循环的次数或者知道循环的范围就使用for循环,其次再使用while循环 猜数字 程序自动生成一个1-100之间的随机数,在代码中使用键盘录入去猜出这个数字是多少? 要求:使用循环猜,一直猜中为止…

Linux[高级管理]——Squid代理服务器的部署和应用(传统模式详解)

🏡作者主页:点击! 👨‍💻Linux高级管理专栏:点击! ⏰️创作时间:2024年6月24日11点11分 🀄️文章质量:95分 目录 ————前言———— Squid功能 Squ…

Lobe Chat openai claude

claude-3-5-sonnet-20240620 $ docker run -d -p 3210:3210 \-e OPENAI_API_KEYsk-xxxx \-e OPENAI_PROXY_URLhttps://api-proxy.com/v1 \-e ACCESS_CODElobe66 \--name lobe-chat \lobehub/lobe-chatDocker 部署 更新 docker ps CONTAINER ID IMAGE …

字节跳动联手博通:5nm AI芯片诞生了?

字节跳动联手博通:5nm AI芯片诞生了? 前言 就在6月24日,字节跳动正在与美国博通合作开发一款5纳米工艺的专用集成电路(ASIC) AI处理器。这款芯片旨在降低采购成本并确保高端AI芯片的稳定供应。 根据报道,尽管芯片设计工作进展顺利…

使用 frida hook Android app

Frida: 一种基于动态插装(dynamic instrumentation)技术的工具包,它主要是为测试人员、开发人员和逆向工程爱好者创建,在目标程序运行时,允许用户将 JavaScript代码注入其中,实现动态修改和调试…

如何恢复Excel保存前的数据?分享5个实用技巧!

在数字化时代,Excel表格已经成为我们工作生活中不可或缺的一部分。然而,随着数据的日益增多,误操作或系统崩溃导致的数据丢失问题也日益突出。但你知道吗?数据其实并没有真正消失,它们只是被隐藏在了电脑深处的某个角落…

手机卡顿反应慢怎么解决?4个实用技巧,轻松提升运行速度

当你的手机变得像一只蜗牛一样缓慢,每一个滑动、每一次点击都充满了无尽的等待,是不是让你感到无比沮丧?别担心,你并不孤单。手机卡顿、反应慢是许多用户都会遇到的问题。那么,手机卡顿反应慢怎么解决呢?本…

智慧仓储的秘密武器:数据可视化的应用

智慧仓储中数据可视化是如何应用的?在现代物流和供应链管理中,智慧仓储已成为企业提升效率、降低成本和优化运营的重要手段。而数据可视化作为智慧仓储的重要工具,通过将复杂的数据转化为直观、易理解的图表和图形,极大地提升了仓…

VOSviewer分析知网文献

VOSviewer简介 VOSviewer 是一款用于构建和可视化科学文献计量网络的软件工具。它能够帮助用户分析和可视化期刊、研究人员或单个出版物之间的关系,这些关系可以基于引用、共引、共著或术语共现关系来构建。VOSviewer 还提供了文本挖掘功能,可以用来构建…

uni-app系列:uni.navigateTo传值跳转

文章目录 1. 使用URL参数2. 使用页面栈注意事项:uni.navigateTo API 参数详细说明回调函数参数 在uni-app中,如果想要通过uni.navigateTo方法跳转到另一个页面并传递参数,可以使用页面路由的URL参数或者页面栈的方式来传递。但是,…

eNSP中静态NAT和动态NAT的配置和使用

一、静态NAT 1.拓扑图 a.新建拓扑图 b.PC端配置 PC1: PC2&#xff1a; c.路由器配置 AR1: <Huawei>system-view [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEthernet0/0/0]ip address 192.168.1.254 24 [R1-GigabitEthernet0/0/0]quit…
最新文章