详解动态库和静态库

在这里插入图片描述

文章目录

  • 前言
  • 静态库
    • 静态库制作
    • 静态库的生成
    • 发布静态库
    • 使用静态库
    • 安装静态库
    • 卸载静态库
  • 动态库
    • 动态库的制作
    • 动态库的生成
    • 动态库的发布
    • 使用动态库
  • 动态库VS静态库

前言

在C、C++中我们使用过标准库,比如在使用strerrorvectorstring等时,都只是调用了这些函数接口,这些都是需要具体的实现。

让我们来看看C语言库:

在这里插入图片描述
将来运行程序,需要二进制文件和库文件

看下C++标准库:

在这里插入图片描述

在Linux系统中,.so结尾是动态库,以.a结尾是静态库;
在Windows中,.dll结尾是动态库,lib结尾是静态库。

静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

.c文件可形成一个.o文件,将这些.o文件链接形成可执行文件,头文件是一个手册,提供函数声明,告诉用户如何使用,.o文件提供实现,我们只需要补充一个main文件,调用头文件提供的方法,然后和.o文件进行连接,就能形成可执行文件。

静态库制作

简单制作一个静态库

// add.h
#pragma onceint add(int x, int y);
// add.c
#include "add.h"int add(int x, int y)
{return x + y;
}
// sub.h
#pragma onceint sub(int x, int y);
// sub.c
#include "sub.h"int sub(int x, int y)
{return x - y;
}

静态库的生成

静态库生成指令:ar -rc lib静态库名.a 需要形成静态库的文件ar是gnu归档工具,rc表示replace and create

静态库的形成本质上是将所有的.o文件打包,因此需要先生成.o文件

在这里插入图片描述

在这里插入图片描述

发布静态库

发布静态库就是自己的lib拷贝给比人

在这里插入图片描述

例如上图是我自己制作的一个简单静态库,只需要将mylib拷贝给别人即可。

使用静态库

将自己的mylib拷贝到一个test文件夹中,然后写一个main.c文件,用于测试静态库的使用

mian.c:

#include "add.h"    
#include "sub.h"                                                                      
#include <stdio.h>           int main()                   {                            printf("1 + 2 = %d\n", add(1, 2));    printf("1 - 2 = %d\n", sub(1, 2));    return 0;                                                        } 

编译:

在这里插入图片描述

这里报错了,说找不到对应的头文件
头文件一般有以下两种方式来包含头文件:

  1. 使用<>来包含头文件,表示到系统指定目录下去查找头文件
  2. 使用" "来包含头文件,这种方式一般用于包含自己所写的头文件中,表示在当前源文件的统计目录下查找头文件,找到了就用,没找到再去系统指定目录下进行查找,所以对于库提供的头文件我们也可以使用 " " 进行包含。

main.c文件中,就是使用" "来包含我所写的头文件,但是还是会报错,理由:使用" "所包含的头文件,会告诉编译器在main.c同级目录下(即test目录下)查找对应的头文件,但是add.hsub.h文件在test文件中的mylib文件中,因此无法找到。

解决上述有三种方式:

  1. 将头文件直接拷贝到当前目录下
  2. 在代码中头文件的路劲补全,如:#include " /mylib/include/add.h "
  3. 在执行 gcc 指令编译的时候加上 -I 选项,指定编译器搜索头文件的路径
    系统默认的指定路劲:/usr/include
    在这里插入图片描述

使用方法3:gcc main.c -I ./mylib/include
在这里插入图片描述
此时依然没有编译成功,此时不是找不到头文件,而是链接错误。gcc在编译的时候,只会去默认路径下查找打包的头文件,不会去/mylib/include中查找,编译器在gcc是就找不到我的酷libmyc.a,也就是编译链接失败。
在这里插入图片描述

此时可以形成main.o文件:
在这里插入图片描述
解决此错误有两种方法:

  1. 将我们的库拷贝到系统的指定路径下,并不能完全解决,还需要指定库的名称
  2. 在使用 gcc 的时候添加对应的选项
  • -L 指定库路径
  • -l 指定库名

在这里插入图片描述

为什么在搜索头文件的时候仅需指定路径呢?当你编译程序时,编译器会首先在这些默认路径下搜索所需的头文件。
在代码中已经写了头文件的具体名称,所以仅需指定头文件的路径即可。而一个路径下可以有多个库,如果只指定路劲,编译器还是不知道该去链接哪个库,因此还要在后面使用 -l 选项指定待链接的库的具体名称。

注意:去掉前缀 lib 和 后缀 .a 才是一个库的名称,建议 -l 后面紧跟库的名称。一般在使用第三方库的时候,可能不需要带 -I 或者 -L,但是 -l 指定库的名称是一定需要到,因为 gcc 默认只能找到系统调用和语言层面的库。

安装静态库

在这里插入图片描述

静态库的安装本质上就拷贝到系统的特定目录下。

卸载静态库

卸载静态库本质是将.h文件和自己的静态库从默认的路劲中删除,此时就无法通过静态库来运行程序。

在这里插入图片描述
在这里插入图片描述

动态库

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

动态库的制作

简单制作一个动态库

// add.h
#pragma onceint add(int x, int y);
// add.c
#include "add.h"int add(int x, int y)
{return x + y;
}
// sub.h
#pragma onceint sub(int x, int y);
// sub.c
#include "sub.h"int sub(int x, int y)
{return x - y;
}

动态库的生成

  • fPIC:产生位置无关码(position independent code)
  • shared: 表示生成共享库格式
  • 库名规则:libxxx.so

在这里插入图片描述
在这里插入图片描述

libmyc.so就是生成的动态库

动态库的发布

将动态库拷贝到刚刚我们静态库的位置

在这里插入图片描述

使用动态库

mian.c:

#include "add.h"    
#include "sub.h"                                                                      
#include <stdio.h>           int main()                   {                            printf("1 + 2 = %d\n", add(1, 2));    printf("1 - 2 = %d\n", sub(1, 2));    return 0;                                                        } 

按照静态库的使用方法,来使用静态库:

在这里插入图片描述
虽然生成了可执行文件,但是可执行文件出错了

使用ldd a.out时,发现libmyc.so => not found,动态库没有被找到,编译期间已经告诉系统对应的头文件以及库的位置,但是这是告诉编译器,没有告诉操作系统,因此编译通过,但是无法运行。
动态库要在程序运行的时候要找到动态库加载运行。静态库为什么没有这个问题?因为静态库在编译期间已经将库中的代码拷贝到可执行程序内部了,加载和库就没有关系了。

解决该问题,有以下四种方法:

  1. 将库文件拷贝到系统默认的库路(/lib64/usr/lib64),不推荐使用这种方法,因为修改了系统规定的库,降低了系统的健康指数
  2. 在系统默认的库路径(/lib64/usr/lib64)下建立软链接
    在这里插入图片描述
  3. 将自己库所在的路径,添加到系统的环境变量 LD_LIBRARY_PATH 中,该环境变量就是专门用来搜索动态库的
    在这里插入图片描述
    但是重新启动系统后,就找不到该环境变量,如果想让系统启动时自动添加该路径到 LD_LIBRARY_PATH 环境变量中,可以通过修改 ~/.bash_profile 中的配置去实现,但是不推荐这么写,不建议修改环境变量。
  4. 如果想让我们的库和系统、语言自带的库一样,在程序运行的时候可以自动被找到,那我们可以/etc/ld.so.conf.d 路径下添加一个 .conf 结尾的配置文件
    在这里插入图片描述
    该配置文件里面的内容就是我们自己动态库所在的路径。添加完后执行 ldconfig 指令,将所有的配置文件重现加载一下,然后程序就能够正常运行。
    在这里插入图片描述
    在这里插入图片描述
    此时程序就可以正常运行:

在这里插入图片描述

动态库VS静态库

动静态库同时存在时,默认连接的是动态库:

在这里插入图片描述
此时对应的可执行程序的体积很小:

在这里插入图片描述

那么如何使用静态库?
只需在后面加一个-static

在这里插入图片描述
此时对应的可执行文件体积很大:

在这里插入图片描述

如果你没有使用-static并且只提供.a,只能静态库连接当前的.a库,其他库正常动态连接。

-static的意义是什么呢?
必须强制的将程序进行静态连接,这就要求连接的任何库都必须提供对应的静态库版本。

在这里插入图片描述

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

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

相关文章

【对算法期中卷子的解析和反思】

一、程序阅读并回答问题&#xff08;共30分&#xff09; #include<cstdio>#include<cstring>#include<iostream>using namespace std;char chess[10][10];int sign[10];int n, k, ans;void dfs(int x, int k) { if (k 0){ans;return; } if (xk-1 >…

智能学工系统实现学生管理

人才培养是高校的榜首要务&#xff0c;高校在抓好学生教育作业的一起&#xff0c;更多的是要加强对学生的办理作业。作为在校大学生健康成长的指导者和引路人&#xff0c;面临很多的学生办理作业内容杂乱&#xff0c;事无巨细&#xff0c;但在传统的办理方式下&#xff0c;尽管…

Java集合:数据存储与操作的瑞士军刀

Java集合概述 集合是用来存储多个元素的容器。文章从四个方面来概述下集合&#xff0c;让读者对集合有一个大致的了解。 一、 多样化的容器 Java 集合大致包含 2 大体系 Collection体系 List&#xff1a;存储有序、重复的元素 Set&#xff1a;存储无序、不可重复的元素…

摸鱼大数据——Hive函数7-9

7、日期时间函数 Hive函数链接&#xff1a;LanguageManual UDF - Apache Hive - Apache Software Foundation SimpleDateFormat (Java Platform SE 8 ) current_timestamp: 获取时间原点到现在的秒/毫秒,底层自动转换方便查看的日期格式 常用 to_date: 字符串格式时间…

【Self-Attention——Transform—Bert】相关的基础理论

1.Self-Attention模型图解 传统的循环神经网络&#xff0c;如上左图1&#xff0c;并不能解决并行化的问题&#xff0c;右图就是一个self-Attention可以实现并行化&#xff0c;并且能解决对于所有信息的读取利用。 将self—Attention替换相应的GRU或者RNN&#xff0c;就能实现从…

单片机原理及应用复习

单片机原理及应用 第二章 在AT89S52单片机中&#xff0c;如果采用6MHz晶振&#xff0c;一个机器周期为 2us 。 时钟周期Tocs1focs 机器周期 Tcy12focs 指令周期&#xff1a;一条指令所用的时间&#xff0c;单字和双字节指令一般为单机器周期和双机器周期。 AT89S5…

Sentinel限流学习

Sentinel限流学习 初识Sentinel运行sentinel雪崩问题服务保护技术对比微服务整合Sentinel 限流规则簇点链路 流控模式-关联流控模式-链路流控模式有哪些&#xff1f; 流控效果流控效果-warm up流控效果-排队等待 热点参数限流隔离和降级Feign整合Sentinel线程隔离有两种方式实现…

【论文复现|智能算法改进】基于多策略麻雀搜索算法的机器人路径规划

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】麻雀搜索算法&#xff08;SSA&#xff09;原理及实现 2.改进点 改进的无限折叠迭代混沌映射 无限折叠迭代映射(ICMIC) 常用于图像加密方向的研究, 基本思想是首先生成[0,1]之间的混沌序列, …

摸鱼大数据——Hive函数10-12

10、堆内存错误 报错&#xff1a; Error while processing statement: FAILED: Execution Error, return code -101 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask. Java heap space 解决方案: 在node1上面操作即可 方式1: 找到/export/server/hive/conf/hive-env.sh,添…

CTF本地靶场搭建——静态flag题型的创建

静态flag题型的创建 首先这里要说的是静态flag和动态flag。 在CTF&#xff08;Capture The Flag&#xff09;比赛中&#xff0c;静态flag的使用通常与特定的赛制或题目类型关联&#xff0c;而不是直接与题型绑定。静态flag意味着这些flag是预先设定好的&#xff0c;不会随比…

MySQL 导出导入的101个坑

最近接到一个业务自行运维的MySQL库迁移至标准化环境的需求&#xff0c;库不大&#xff0c;迁移方式也很简单&#xff0c;由开发用myqldump导出数据、DBA导入&#xff0c;但迁移过程坎坷十足&#xff0c;记录一下遇到的各项报错及后续迁移注意事项。 一、 概要 空间问题源与目…

排序进阶----快速排序

当我们写了插入和希尔排序后&#xff0c;我们就应该搞更难的了吧。大家看名字就知道我们这篇博客的内容了吧。而且从名字上来看。快速排序就很快吧。那么为什么这个排序怎么能叫快速排序啊。我们希尔排序不是很快嘛。那么我们的快速排序肯定是有特殊之处嘞。不然这就太自负了。…

autodl服务器中YOLOx训练自己数据集

目录 本篇文章主要讲解使用YOLOx训练自己数据集&#xff0c;其中包括数据集格式转换~ 目录 一、数据集处理二、环境配置三、配置文件修改四、开始训练五、开始验证 一、数据集处理 第一步&#xff1a;将yolo格式的数据集转换成VOC格式 转换脚本&#xff1a;txt_to_xml.py f…

Unity DOTS技术(二)ECS

文章目录 一.ECS简介二.基本操作实例三.实体查看组件四.位置实体修改五.旋转实体六.了解原有属性七.禁止自动创建八.动态实例化 一.ECS简介 ECS全称 (Entity Component System).即(E:实体 C:组件 S:系统). 实际上即是数据方法分离.数据放在组件里,具体实现放在系统里.组件挂载…

Debian系统磁盘挂载

服务器推荐&#xff1a;雨云 优惠码&#xff1a;zsj 用优惠码注册账户并绑定微信后可获取首月5折优惠券&#xff1b; 后续新购主机也可在积分商城中换取新购优惠券&#xff1b; 公测阶段的超大带宽服务器&#xff0c;由于是国内主机因此需要备案域名。 公测阶段价格尚未确定&am…

google的chromedriver最新版下载地址

Chrome for Testing availability (googlechromelabs.github.io) 复制对应的地址跳转进去即可下载&#xff0c;下载前先看下自己google浏览器版本&#xff0c;找到对应的版本号去下载&#xff0c;把解压缩的exe放到google浏览器目录下。

使用python统计word文档页数

使用python统计word文档页数 介绍效果代码 介绍 使用python统计word文档的页数 效果 代码 import os import comtypes.clientdef get_word_page_count(docx_path):try:# Initialize the COM objectword comtypes.client.CreateObject(Word.Application)word.Visible False…

Nature Communications|柔性自驱动仿生眼(离子凝胶/仿生眼/柔性电子)

2024年4月10日,黄维(Wei Huang)院士、南京工业大学刘举庆(Juqing Liu)教授和刘正东(Zhengdong Liu)副教授课题组,在《Nature Communications》上发布了一篇题为“A bionic self-driven retinomorphic eye with ionogel photosynaptic retina”的论文,罗旭(Xu Luo)、陈晨(…

ESP-01S 使用 arduino 烧录程序

一、设置 arduino 编辑器 1、文件-首选项-附加开发版管理网址中添加 http://arduino.esp8266.com/stable/package_esp8266com_index.json 2、工具-开发板管理 搜索 8266 并下载 ) 3、工具-开发板 在 8266 里面选择 Generic ESP8266 Module 4、工具-端口 记得选择对应的端口 …