linux-动态库和静态库制作和使用

news2024/11/17 23:38:56

【静态连接和动态连接】C/C++编程中的两种有效链接策略_c++ 动态链接 静态链接_SecureCode的博客-CSDN博客

静、动态库概念和各自优点

静:

动:

动态库:只有一份,运行时具体代码行才加载使用(相对慢);

静态库:编译时候一块编进去,用几处编几份,执行速度快场景。

从静态到动态是一个时间换空间的过程。

静态库制作、使用以及gcc常见报错处理

将几个内涵若干个函数的.c文件,先各自处理为 .o文件。

然后,执行静态库制作的命令。生成的 .a 文件即为制作好的静态库文件了。

注意:库的命名必须以 lib 开头,静态库要以 .a 结尾

使用静态库(把库和调用文件一块编译即可生成 .out可执行文件即可);

gcc报错,一般有两种阶段多见,编译和链接。

报错,有行号,说明是编译阶段报错,一般也是语法检查出错了;

没行号,说明已经是二进制了,是链接阶段报错。

根据上面的使用方法,给gcc 再加一个 -Wall 参数,出现告警信息。分析,下面的报错显然是编译阶段:

原因:显然是调用文件.c中没有声明 使用的库函数;

解决办法:再另外做一个静态库头文件。

放在编译文件所在目录下,再执行原来的编译命令,就没问题了。

加强:静态库制作的时候,注意另外给静态库.a制作一个.h头文件。然后在主函数里面include里面加。完事在头文件所在目录下执行目标文件的编译命令。避免编译器帮你隐式声明而导致的不必要的问题

万恶之源:C语言中的隐式函数声明_隐式声明-CSDN博客1 什么是C语言的隐式函数声明在C语言中,函数在调用前不一定非要声明。如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码。下面是一个例子:int main(int argc, char** argv){ double x = any_name_function(); return 0;}单纯的编译上述源代码,并没有任何报错,只是在链接阶段因为找_隐式声明https://blog.csdn.net/smstong/article/details/50523120?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-6-50523120-blog-124943920.235%5Ev38%5Epc_relevant_anti_vip_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-6-50523120-blog-124943920.235%5Ev38%5Epc_relevant_anti_vip_base&utm_relevant_index=11

动态库的制作及使用(与静态库大体相同,特别注意区别):

动态库的制作

注意和静态库的关键区别:

动态库是只有调用到相关方法时,相关库才被加载到内存中被使用。而静态库是在编译时候,静态方法在代码里的位置已经相对main函数确定了。因此,基于这一点区别动态库在制作时,制作库的相关命令参数 稍有不同【要生成与位置无关的代码 借助参数 -fPIC】。

代码:

//add.c
int add(int a, int b)
{
​    return a+b;
}
//sub.c
int sub(int a, int b)
{
​    return a-b;
}
//test.c文件
//不需要包含add.c和sub.c文件,也可以加进行编译工作,但是会提示错误
#include <stdio.h>
int main(int argc, char** argv)

{
​    int a=20,b=10;
​    printf("a+b=%d\n",add(a,b));
​    printf("a-b=%d\n",sub(a,b));
​    return 0;
}
//库头文件
#ifndef _CAL_H
#define _CAL_H
int add(int, int);
int sub(int, int);
#endif

1.分别将 .c 库函数文件生成 .o文件;

动态库要求生成与位置无关的代码(函数调用之前需要将其地址固定)

数据段合并和地址回填 延迟绑定(动态库函数的地址比主函数的其它调用函数分配地址要晚)

结论:制作动态库的.o文件和静态库有区别,生成位置无关文件,借助 -fPIC选项

gcc -c add.c -o add.o -fPIC


2.使用gcc 和 -shared选项将所有 .o库文件制作成一个动态库文件

gcc -shared -o lib库名.so add.o sub.o


3.编译可执行程序时,指定所使用的动态库, -l和-L

-l:用来指定库名 -L:用来指定库路径

gcc test.c -o a.out -lcal(cal是库名) -L./lib

至此,包含了库的可执行文件就生成了。下面开始执行代码:

(执行过程中会有问题,就是库钓不上,因此还有一步要补充,后面会提到)

4.运行可执行程序;

./a.out
————————————————
版权声明:本文为CSDN博主「CPPlusQt」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Blunt_Du/article/details/122329243

动态库路径环境变量的添加

按照上述方法,制作一个动态文件执行后,

报错:

原因:

是找不到自己在某个目录下做的动态文件。准确地说,是程序执行的时候 动态连接器 没有找到程序中使用的动态库。(注意这句话要和制作动态库的时候“链接器”指定动态库目录区分开,完全不同阶段的东西)

概念区分:

链接器 (编译阶段):工作于链接阶段,工作时需要 -l和-L选项(用于编译静态库)

动态链接器 (运行阶段):工作于程序运行阶段,工作时需要提供动态库所在目录位置;

可以使用ldd命令--查出可执行文件依赖了哪些动态库

ldd是list, dynamic, dependencies的缩写, 意思是, 列出动态库依赖关系。

Linux中的8个ldd命令示例_ldd -r-CSDN博客

看上面的依赖显示,c库其实也是一个动态链接库

解决办法:

想办法让 a.out执行的阶段,能找到它使用的so库。即需要适时指定一个路径。

具体解决方案:

解决方法:

方案1:临时修改该用户下 bash的环境变量

程序运行时候,会由一个环境变量(里面存了很多路径)指向动态库在哪。我们在当前shell临时更新下这个环境变量即可。

 
#环境变量生效:
export LD_LIBRARY_PATH=./lib
#上面填入的是相对路径,如果要一直生效,最好填入绝对路径
#运行程序
./a.out

存在不足:环境变量是依赖于终端的,切换终端之后,新的终端的环境变量会失效

linux 环境变量icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/132511548LD_LIBRARY_PATH用法详解-CSDN博客LD_LIBRARY_PATH_ld_library_pathhttps://blog.csdn.net/m0_58235748/article/details/130557000?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169699099116800182196576%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169699099116800182196576&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-130557000-null-null.142%5Ev95%5Einsert_down28v1&utm_term=LD_LIBRARY_PATH&spm=1018.2226.3001.4187

方案2:修改该用户下 bash的环境变量配置文件:

(1) 通过gedit或者vi修改bash的配置文件;

#脚本的名字为.bashrc

gedit ~/.bashrc
#或者使用vim打开
vi ~/.bashrc

(2)在终端中添加动态库路径

export LD_LIBRARY_PATH=动态库路径

建议使用绝对路径

(3)使脚本文件生效,通过运行脚本文件实现、

. .bashrc    
#或者
source .bashrc
#或者重启终端,每次重启终端,bashrc都会运行


方案3:拷贝自定义动态库到标准C库(不推荐)

 
标准C库也是通过动态库进行加载的,而且可以加载成功,这给我们的提示是可以把这个生成的动态库拷贝到C库的文件夹中

sudo cp libmymath.so /lib

然后把原来设置的环境变量删掉。

方案4:配置文件法

 
#打开配置文件

sudo vi /etc/ld.so.conf

在配置文件中写入库文件目录所在位置,最好写入绝对目录

让配置文件生效

#-v选项会在终端显示动态库的加载位置

sudo ldconfig -v

运行程序生效

总结四种方法:

————————————————
原文链接:https://blog.csdn.net/Blunt_Du/article/details/122329243

可以通过下面的命令查看运行程序运行之后,需要加载那些动态库,以及动态库的路径

ldd a.out

知识补充:在静、动态库这块知识方面,gcc还需要补充学习几个参数

gcc   - 参数

-I ( i 大写)  :指定头文件路径(相对路径或觉得路径,建议相对路径)

-i               :指定头文件名字 (一般不用,而是直接放在**.c 文件通过#include<***.h> 添加)

-L              :指定连接的动态库或者静态库路径(相对路径或觉得路径,建议相对路径)

-l (L小写)   :指定需要链接的库的名字(链接 libc.a :-lc       链接动态库:libc.so  : -lc   注意:-l后面直接添加库名省区“lib”和“.so”或“.a”  )

————————————————
原文链接:https://blog.csdn.net/abcdu1/article/details/86083295

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

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

相关文章

FastAPI学习-27 使用@app.api_route() 设置多种请求方式

对同一个访问函数设置多个http 请求方式 api_route 使用 使用methods 参数设置请求方式 from fastapi import FastAPIapp FastAPI() app.api_route(/demo/b, methods[get, post]) async def demo2(): return {"msg": "demo2 success"}判断请求方式…

FreeRTOS学习笔记——四、任务的定义与任务切换的实现

FreeRTOS学习笔记——四、任务的定义与任务切换的实现 0 前言1 什么是任务2 创建任务2.1 定义任务栈2.2 定义任务函数2.3 定义任务控制块2.4 实现任务创建函数2.4.1 任务创建函数 —— xTaskCreateStatic()函数2.4.2 创建新任务——prvInitialiseNewTask()函数2.4.3 初始化任务…

08. 机器学习- 线性回归

文章目录 线性回归 LINEAR REGRESSION 从本次课程开始&#xff0c;大部分时候我将不再将打印结果贴出来了&#xff0c;因为太占用篇幅。小伙伴可以根据我的输出执行敲一遍代码来进行学习和验证。 同样是为了节省篇幅&#xff0c;我也不会再一行行那么仔细的解释代码了&#xff…

学信息系统项目管理师第4版系列24_整合管理

1. PMBOK 1.1. 自1987年以来&#xff0c;PMBOK-直是基于过程的项目管理标准的重要代表 1.1.1. 基于过程的方法是项目管理的基石 1.2. 从2021年开始&#xff0c;第7版PMBOK采用了基于原则的标准&#xff0c;其中包含了 12个项目管理基本原则&#xff0c;这些基本原则为有效的…

android studio 我遇到的Task :app:compileDebugJavaWithJavac FAILED问题及解决过程

前几天一个网友在学习我的一个小项目的时候&#xff0c;发现无法达到目的&#xff0c;在帮他解决问题的过程中发现他用的是最近的giraffe版本的as&#xff0c;我用的是老版本&#xff0c;没办法打开他的项目&#xff0c;没办法只能卸载我的as&#xff0c;安装了最近版的diraffe…

【计算机网络笔记】计算机网络的结构

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 文章目录 系列文章目录网络边缘接入网络数字用户线路 (DSL)电缆网络典型家庭网络的接入机构&#xff08;企业&#xff09;接入网络 (Ethernet)无线接入网络 网络核心Internet结构最后 计算机网络的结构…

排序算法-快速排序法(QuickSort)

排序算法-快速排序法&#xff08;QuickSort&#xff09; 1、说明 快速排序法是由C.A.R.Hoare提出来的。快速排序法又称分割交换排序法&#xff0c;是目前公认的最佳排序法&#xff0c;也是使用分而治之&#xff08;Divide and Conquer&#xff09;的方式&#xff0c;会先在数…

整理mongodb文档:副本集成员可以为偶数

个人博客 整理mongodb文档:副本集成员可以为偶数 想了下&#xff0c;仲裁节点还是不想直接说太多&#xff0c;怕有的同学想太多&#xff0c;且本身副本集就偏向运维的&#xff0c;新手基本也没什么权限操作&#xff0c;就不多废话了。 文章概叙 文章从MongoDB是否可以用偶数…

Redis - php通过ssh方式连接到redis服务器

1.应用场景 主要用于使用php通过ssh方式连接到redis服务器&#xff0c;进行一些操作. 2.学习/操作 1.文档阅读 chatgpt & 其他资料 SSH - 学习与实践探究_ssh应用场景 2.整理输出 2.1 是什么 TBD 2.2 为什么需要「应用场景」 TBD 2.3 什么时候出现「历史发展」 TBD 2.4 …

解决mac系统终端无法使用vpn

解决mac系统终端无法使用vpn 换了公司新电脑&#xff0c;以前用vpn都是直接都可以访问&#xff0c;这次换了电脑和vpn&#xff08;这里用的海豚湾&#xff09;就发现访问不了huggingface.co了&#xff0c;无法git clone 下载大模型真的很难受。 解决方法&#xff1a; 查看自…

Maven Eclipse

Eclipse 提供了一个很好的插件 m2eclipse &#xff0c;该插件能将 Maven 和 Eclipse 集成在一起。 在最新的 Eclipse 中自带了 Maven&#xff0c;我们打开&#xff0c;Windows->Preferences&#xff0c;如果会出现下面的画面&#xff1a; 下面列出 m2eclipse 的一些特点&a…

【已编译资料】基于正点原子alpha开发板的第三篇系统移植

系统移植的三大步骤如下&#xff1a; 系统uboot移植系统linux移植系统rootfs制作 一言难尽&#xff0c;踩了不少坑&#xff0c;当时只是想学习驱动开发&#xff0c;发现必须要将第三篇系统移植弄好才可以学习后面驱动&#xff0c;现将移植好的文件分享出来&#xff1a; 仓库&…

第五十二章 学习常用技能 - Global 映射

文章目录 第五十二章 学习常用技能定义数据库定义命名空间Global映射 第五十二章 学习常用技能 定义数据库 创建本地数据库&#xff1a; 登录管理门户。选择系统管理 > 配置 > 系统配置 > 本地数据库。选择创建新数据库以打开数据库向导。输入新数据库的以下信息&a…

libjpeg库

库安装就不说了&#xff0c;我是直接下载编译好的库 Independent JPEG Group (ijg.org) 这个需要自己编译 可以使用的代码 #include <stdio.h> #include <jpeglib.h> #include <stdlib.h>void compress_jpeg(const char* input_filename, const char* outp…

域名,二级域名,局域网自定义域名

什么是域名 域名是互联网上用于标识和定位网站的字符串。它提供了一个易于记忆和使用的方式来访问网站&#xff0c;代替了使用 IP 地址的复杂形式。域名通常由多个部分组成&#xff0c;用点&#xff08;.&#xff09;分隔。 域名的结构是从右向左逐级划分的&#xff0c;每个部…

原理:用UE5制作一个2D游戏

选中资产图片右键--Sprite Actions--Apply Paper2D Texture Settings 制作场景 把它丢到场景里&#xff0c;并把坐标归零 创建图块集tileset 打开新建的tile set&#xff0c;根据最小图块设置最小尺寸单元 选择需要的图块单元&#xff0c;add box 对新建的tile set右键创建til…

UI 自动化测试框架:PO 模式+数据驱动!

1. PO 设计模式简介 什么是 PO 模式&#xff1f; PO&#xff08;PageObject&#xff09;设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类&#xff0c;并以页面为单位来写测试用例&#xff0c;实现页面对象和测试用例的分离。 PO 模式的设计思想与…

msvcp120.dll是什么东西?找不到msvcp120.dll怎么修复?

在计算机技术的世界里&#xff0c;我们经常会遇到各种错误和问题。其中之一就是MSVCP120.dll的丢失。这是一个非常常见的问题&#xff0c;许多用户在运行某些程序时会遇到这个错误。 MSVCP120.dll是什么&#xff1f; MSVCP120.dll&#xff0c;全名是Microsoft Visual C Runti…

Netty深入浅出Java网络编程学习笔记(二) Netty进阶应用篇

目录 四、应用 1、粘包与半包 现象分析 粘包 半包 本质 解决方案 短链接 定长解码器 行解码器 长度字段解码器——LTC 2、协议设计与解析 协议的作用 Redis协议 HTTP协议 自定义协议 组成要素 编码器与解码器 编写测试类 Sharable注解 自定义编解码器能否使用Sharable注解 3、在…

Python jieba库的使用说明

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一、jieba库基本介绍 jieba库概述 jieba是优秀的中文分词第三方库 中文文本需要通过分词获得单个的词语 jieba是优秀的中文分词第三方库&#xff0c;需要额外安…