125 Linux C++ 系统编程4 Linux 静态库制作,动态库制作,静态库和动态库对比。静态库运行时找不到库的bug fix

一 静态库 和动态库 对比

静态库的原理:假设我们有一个 静态库,大小为500M,这个静态库实现了一些打牌的逻辑算法,提供了一堆API,让开发者 可以轻松的实现 54张扑克牌的随机发牌,指定发牌等功能。

我们写了一个腾讯的棋牌类游戏,在牌类中,有斗地主,够级,升级等游戏,很显然,每一个单独的游戏都是一个 可执行的 .out文件了。

假设叫做 a.out,b.out,c.out

显然这a.out,. b.out,c.out都会用到静态库中的这些方法。

那么静态库 和 每一个 .out结合的样子 ,类似下图:

也就是说:

静态库会被每个.out copy 一份到自己的代码里面。

静态库要求执行效率高,但是会牺牲空间。

操作系统的开机加载的一般都是静态库。

目前静态库的应用比较少,动态库的场景比较多,静态库知道怎么弄,如果今后开发中遇到了,知道怎么实做就可以了。

静态库在应用程序生成后,可以不必再编译,节省再编译时间,如果其他开发人员要使用您的程序,而你又不想给其源码,提供静态库是一种选择。

动态库则不会 被copy

动态库会单独的存放一份,被大家共享,不会被各个 .out文件copy 一份。而是在a.out需要的时候去动态库中找到想要的 api,调用一下。

二 如果制作一个静态库

1.使用写好的 .c.h.cpp文件生成.o文件

        

g++ -c addfunc.cpp -I ./head -o addfunc.o
g++ -c subfunc.cpp -I ./head -o subfunc.o
g++ -c mulfunc.cpp -I ./head -o mulfunc.o
g++ -c devfunc.cpp -I ./head -o devfunc.o

2.build 出来静态库文件,我们这里起名叫做 libdou.a

ar rcs libdou.a addfunc.o subfunc.o mulfunc.o devfunc.o

这时候我们就得到了 libdou.a 

关于1,2的说明

在build 出来静态库之前,是需要生成所有.c 和 .cpp的.o文件的,我们这里将.h文件都放在了head头文件里面

我们使用的代码如下: 有5个文件,一个.h 放在 head文件夹下,4个.cpp文件

dou.h
#pragma once
#include <iostream>
using namespace std;
//目前的状况是:我们是第三方的库开发者,致力于开发一些第三方库卖钱,开发了一个加减乘除的算法库,
//这个算法很先进,使用了AI技术,是8个博士后的心血结晶,我们不希望使用者知道开发的细节,
//因此我们需要提供一个 .h文件,告知使用者你要引入的头文件是这个.h文件
//并且提供了一个静态库给 开发者,libdou.aint addfunc01(int a, int b);
int subfunc02(int a, int b);
int mulfunc03(int a, int b);
int devfunc04(int a, int b);

addfunc.cpp
#include "dou.h"int addfunc01(int a, int b) {return a + b;
}

subfunc.cpp
#include "dou.h"int subfunc02(int a, int b) {return a - b;
}

mulfunc.cpp#include "dou.h"int mulfunc03(int a, int b) {return a * b;
}

devfunc.cpp#include "dou.h"int devfunc04(int a, int b) {if (b == 0) {cout << "devfunc04 error because dividend ==0" << endl;return -1;}return a / b;
}

g++ -c addfunc.cpp -I ./head -o addfunc.o
g++ -c subfunc.cpp -I ./head -o subfunc.o
g++ -c mulfunc.cpp -I ./head -o mulfunc.o
g++ -c devfunc.cpp -I ./head -o devfunc.o
ar rcs libdou.a addfunc.o subfunc.o mulfunc.o devfunc.o

这时候我们就得到了 libdou.a 

3. 第三方公司如何应用

3.0我们卖给第三方公司的就是一个头文件dou.h,和一个libdou.a,

3.1 第三方的有一个 test.cpp,在这个 test.cpp 用到了静态库中的一些方法

需要导入我们的 #include "dou.h"

并且将dou.h 放在和test.cpp 一行的 head目录下

test.cpp
#include <iostream>
#include "dou.h"
using namespace std;int main(){cout<<"a+b = " << addfunc01(10,5)<<endl;cout<<"a-b = " << subfunc02(10,5)<<endl;cout<<"a*b = " << mulfunc03(10,5)<<endl;cout<<"a/b = " << devfunc04(10,5)<<endl;return 0;
}

3.2 将test.cpp 和 静态库文件 libdou.a 静态编译在一起。生出来一个test.out文件

g++ test.cpp libdou.a -o test.out -I ./head

3.3执行 ./test.out

hunandede@hunandede-virtual-machine:~/day02/staticlib$ g++ test.cpp libdou.a -o test.out -I ./head
hunandede@hunandede-virtual-machine:~/day02/staticlib$ ./test.out
a+b = 15
a-b = 5
a*b = 50
a/b = 2

3.4 查看 test.out的大小

我们观察到 最终客户生成的 test.out 占据的大小为 14016,但是实际上我们的test.cpp文件只有269这么大。可见确实 将静态库 build 自己里面了。

三 .动态库的制作和使用

 1.使用写好的 .c.h.cpp文件生成.o文件

  但是这种动态库的.o文件,是和静态库的.o文件不一样。因此制作方法也不一样。

动态库制作.o文件的方法:

g++ -c addfunc.cpp -I ./head -o addfunc.o -fPIC

静态库制作.o文件的方法:

g++ -c addfunc.cpp -I ./head -o addfunc.o

g++ -c addfunc.cpp -I ./head -o addfuncdongtai.o -fPIC
g++ -c subfunc.cpp -I ./head -o subfuncdongtai.o -fPIC
g++ -c mulfunc.cpp -I ./head -o mulfuncdongtai.o -fPIC
g++ -c devfunc.cpp -I ./head -o devfuncdongtai.o -fPIC

如下是两者不同原理性的说明:能看懂就看,看不懂拉倒.记住前面的结论就可以了

静态库中方法的地址是以main为依据,一般都是main的地址+xxx 

例如我们的 addfunc01方法的地址 就是 main的地址+100, (注意,这里100不是一个真实的值,是我们猜测的)

在编译的第四阶段,链接的时候,会将main的地址给定一个确定的值,因此我们调用addfunc01的时候,地址也就确定了

动态库的方法的地址不是以main为依据的,只有在调用到 addfunc01dongtai 方法的时候,才去找真实的地址,因此也叫做动态绑定,查看printf函数的反汇编,会有 <printf@plt>的字样,知道这里就可以了。

2,。使用 g++ -shared 制作动态库

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

使用参数 -shard 

-o 重命名 

lib库名.so  为我们要制作出来的 动态库文件

g++ -shared -o libdoudongtai.so addfuncdongtai.o subfuncdongtai.o mulfuncdongtai.o devfuncdongtai.o 

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

g++ test.cpp -o a.out -lmymath -L./lib

注意我们实现的时候并没有将libdoudongtai.so放在 lib目录下,而是和test.cpp放在一起了,只是将将.h文件放在 head文件夹下。

 g++ test.cpp -o a.out -ldoudongtai -L./ -I./head

4.运行 可执行程序 发生问题

./a.out

./a.out: error while loading shared libraries: libdoudongtai.so: cannot open shared object file: No such file or directory
 

5.动态库 运行原理 以及 bug fix

原因:动态库想要执行需要两个关键的地方:链接器 和 动态链接器

链接器 和 动态链接器没有关系,可以理解为 “张三” 和 “张三丰” 的关系。

        链接器 :工作于编译的 链接阶段,工作时需要 -l 和 -L 支持,我们已经在前面说明了在哪里

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

                                动态库所在目录位置是几个比较固定的位置,我们需要将 动态库所在目录 放在这几个固定的位置,如下的说明,应该是有三个地方

​
当执行函数动态链接.so时,如果此文件不在缺省目录下‘/lib’ and ‘/usr/lib’.那么就需要指定环境变量LD_LIBRARY_PATH​

       1.动态环境变量存放的地方:为 LD_LIBRARY_PATH

                export 表示导入,下面的意思是,导入LD_LIBRARY_PATH为当前文件夹。

                export LD_LIBRARY_PATH=./

                然后执行 ./a.out     结果正常

        2. 当我们将当前的 窗口关闭,然后重新打开一个窗口的时候,cd到当前目录,执行 ./a.out 又无法执行了, 这是因为 LD_LIBRARY_PATH 环境变量是 进程的概念,我们刚才打开的 窗口中执行了 export LD_LIBRARY_PATH=./  当这个窗口关闭后,设置的也就不生效了。

        那么怎么弄呢? 既然窗口关闭后,LD_LIBRARY_PATH 环境变量的值就会使用默认的,那么我们就改动 窗口的配置即可。从前几章的知识我们知道 ,我们在窗口打的字,最终是 shell 解释器在处理内容,然后回复给我们,shell有很多种,而在unbutu中,这个shell 实际上 bash。因此我们改动bash的配置文件就OK了。bash的配置文件叫做 .bashrc   

打开 .bashrc ,添加 export LD_LIBRARY_PATH=./

注意后面的./ 是路径,如果我们这么加,每次都需要进入到 a.out的目录才能执行a.out

建议 改成绝对路径, 打开 .bashrc ,添加 export LD_LIBRARY_PATH=/home/hunandede/day02/dongtaiku/

总结

上面写的太多了。整理

5.1 临时生效方法,只在当前窗口有用

export 表示导入,下面的意思是,导入LD_LIBRARY_PATH为当前文件夹。

                export LD_LIBRARY_PATH=./

        

5.2 永久生效的方法:配置bash的 配置文件 .bashrc

1.打开终端,vim ~/.bashrc

2.在最后一行加上

export LD_LIBRARY_PATH=/home/hunandede/day02/dongtailib

保存,退出

3 执行  . .bashrc/ 重启终端  (这个好像不行,先不管)

或者 source .bashrc  重启终端

或者关闭终端后,重新打开

4.执行 ./a.out

6.动态库bug fix2 ,加入到 ‘/lib’ 或者‘/usr/lib’ 中

当执行函数动态链接.so时,如果此文件不在缺省目录下‘/lib’ and ‘/usr/lib’.

才会去找 LD_LIBRARY_PATH

因此我们也可以将 .so文件copy 一份 放在 根目录下的 /lib文件下。

7.动态库 bug fix3,配置文件方法-- 修改etc/ld.so.conf

1.修改etc/ld.so.conf

sudo vim /etc/ld.so.conf

添加你的共享库路径

2.更新查找共享库的路径 -v 是显示个用户看过程的意思

sudo ldconfig -v

3.测试你的程序可否找到共享库

ldd a.out

8.怎么知道 a.out 文件是否已经有所有的动态库了呢?

可以使用 ldd  a.out 查看

ldd 是这个命令,它会分析 a.out执行起来需要哪些动态库,以及这些动态库执行起来的路径在哪里,如果你的动态库缺失,或者没有配置,则后面为空

如下:我们的 a.out是OK的,因此查看

hunandede@hunandede-virtual-machine:~/day02/dongtailib$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffe28528000)libdoudongtai.so => /home/hunandede/day02/dongtailib/libdoudongtai.so (0x00007fb421ae1000)libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb42175f000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb421395000)libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb42108c000)/lib64/ld-linux-x86-64.so.2 (0x00007fb421ce4000)libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb420e76000)

失败的样子

9.那么这里又有一个问题了,当我们给了user  .h文件和  .so文件后,还要教客户怎么在 配置吗?

实际开发中怎么做的呢?

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

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

相关文章

Python入门学习——基础语法

一、Python解释器 1. Python解释器的作用是&#xff1a; 将Python代码翻译成计算机认识的O和1并提交计算机执行在解释器环境内可以一行行的执行我们输入的代码也可以使用解释器程序&#xff0c;去执行".py"代码文件 2. Python解释器程序在&#xff1a; <Python…

google浏览器chrome无法访问localhost等本地虚拟域名的解决方法

场景一&#xff1a; 谷歌浏览器访问出现&#xff1a;forbbiden 403 问题&#xff0c;或者直接跳转到正式域名(非本地虚拟域名) 访问本地的虚拟域名http://www.hd.com/phpinfo.php?p1发生了302 条状 火狐浏览器正常访问; 解决方法&#xff1a; 方法1&#xff1a;在谷歌浏览器…

Linux的ACL权限以及特殊位和隐藏属性

前言&#xff1a; ACL是什么&#xff1f; ACL&#xff08;Access Control List&#xff09;是一种权限控制机制&#xff0c;用于在Linux系统中对文件和目录进行细粒度的访问控制。传统的Linux权限控制机制基于所有者、所属组和其他用户的三个权限类别&#xff08;读、写、执行…

转运机器人,AGV底盘小车:打造高效、精准的汽车电子生产线

为了满足日益增长的市场需求&#xff0c;保持行业领先地位&#xff0c;某汽车行业电子产品企业引入富唯智能AMR智能搬运机器人及其智能物流解决方案&#xff0c;采用自动化运输措施优化生产节拍和搬运效率&#xff0c;企业生产效率得到显著提升。 项目背景&#xff1a; 1、工厂…

milvus Delete api写s3的流程

Delete api写s3的流程 milvus版本:v2.3.2 整体架构: Delete 的数据流向 delete相关配置 dataNode:segment:insertBufSize: 16777216 # Max buffer size to flush for a single segment.deleteBufBytes: 67108864 # Max buffer size to flush del for a single channelsyncPe…

汽修专用产品---选型介绍 汽修示波器 汽车示波器 汽车电子 汽修波形 汽车传感器波形 汽车检测

为了满足汽车电子用户的测量需求&#xff0c;我司特推出汽修专用版示波器&#xff0c;一键测量&#xff0c;轻松找出汽车问题。 LOTO各种型号的示波器其实都可以用作汽车传感器信号波形的检测。汽修应用中&#xff0c;工程师对示波器的性能要求对于LOTO产品来说不算高。 在我们…

《TCP/IP详解 卷一》第6章 DHCP

目录 6.1 引言 6.2 DHCP 6.2.1 地址池和租用 6.2.2 DHCP和BOOTP消息格式 6.2.3 DHCP和BOOTP选项 6.2.4 DHCP协议操作 6.2.5 DHCPv6 6.2.6 DCHP中继 6.2.7 DHCP认证 6.2.8 重新配置扩展 6.2.9 快速确认 6.2.10 位置信息&#xff08;LCI和LoST&#xff09; 6.2.11 移…

Unity Shader ASE基础效果思路与代码(二):边缘光、扰动火焰

Unity Shader ASE基础效果思路与代码(二)&#xff1a;边缘光、扰动火焰 这里写目录标题 Unity Shader ASE基础效果思路与代码(二)&#xff1a;边缘光、扰动火焰边缘光效果展示&#xff1a;代码与思路&#xff1a; 扰动火焰效果展示&#xff1a;代码与思路&#xff1a; 边缘光 …

snmp协议开通教程

目录 一、什么是snmp协议&#xff1f; 二、snmp协议可以用来干什么&#xff1f; 三、snmp协议的开通 1、snmpv2协议开通 2、snmpv3协议开通 一、什么是snmp协议&#xff1f; SNMP&#xff08;Simple Network Management Protocol&#xff09;是一种用于网络管理的标准协议&a…

STM32物联网(封装AT指令进行TCP连接及数据的接收和发送)

文章目录 前言一、AT指令函数封装1.向ESP8266发送数据函数2.设置ESP8266工作模式3.连接WIFI函数4.查询IP地址5.连接TCP服务器6.发送数据到TCP服务器7.接收并解析来自TCP服务器的数据8.关闭TCP服务器 二、代码测试总结 前言 本篇文章将继续带大家学习STM32物联网&#xff0c;那…

Vue 2.0 中的 Vuex Store 状态管理器核心概念和组成部分

Vue 2.0 中的 Vuex Store 状态管理器核心概念和组成部分 State&#xff08;状态&#xff09;&#xff1a; Vuex Store 的核心就是集中式存储应用的所有组件的状态。它是一个单一状态树&#xff0c;所有的组件都从这个状态树中读取数据并可以响应状态的变化。 const state {c…

Ubuntu20.04 查看系统版本号

目录 uname -auname -vlsb_release -acat /etc/issuecat /proc/version uname -a 查看系统发行版本号和操作系统版本 uname -v 查看版本号 lsb_release -a 查看发行版本信息 cat /etc/issue 查看系统版本 cat /proc/version 查看内核的版本号

计算机网络面经_体系结构一文说清

编辑&#xff1a;平平无奇的羊 目录 基础 1. 计算机网络结构体系 三种模型之间的区别&#xff1a; 如何背诵&#xff1a; 进阶 OSI七层模型&#xff1a; TCP/IP四层模型&#xff1a; TCP/IP五层模型 总结 字节实习生为大家带来的是计算机网络面经系列博文&#xff0c;由浅…

分散的产品开发团队

分散的产品开发团队指的是各个团队或成员在地理位置上分布在不同地方&#xff0c;通过互联网和现代通讯技术进行协作和沟通&#xff0c;以共同完成产品开发任务的团队模式。 这种团队模式的优势在于可以充分利用各地的人才资源&#xff0c;降低团队的管理和协作成本&#xff0…

SpringBoot和SpringCloud的区别,使用微服务的好处和缺点

SpringBoot是一个用于快速开发单个Spring应用程序的框架&#xff0c;通过提供默认配置和约定大于配置的方式&#xff0c;快速搭建基于Spring的应用。让程序员更专注于业务逻辑的编写&#xff0c;不需要过多关注配置细节。可以看成是一种快速搭建房子的工具包&#xff0c;不用从…

ThreeJS 几何体顶点position、法向量normal及uv坐标 | UV映射 - 法向量 - 包围盒

文章目录 几何体的顶点position、法向量normal及uv坐标UV映射UV坐标系UV坐标与顶点坐标设置UV坐标案例1&#xff1a;使用PlaneGeometry创建平面缓存几何体案例2&#xff1a;使用BufferGeometry创建平面缓存几何体 法向量 - 顶点法向量光照计算案例1&#xff1a;不设置顶点法向量…

探讨javascript中运算符优先级

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 深入理解JavaScript运算符优先级运算符优先级概述示例演示示例1&#xff1a;加法和乘法运算符的优先级示…

CentOS7 安装Python3.8

在 CentOS 7 上&#xff0c;按照以下步骤安装 Python 3.8&#xff1a; 添加EPEL仓库&#xff1a;首先安装 EPEL&#xff08;Extra Packages for Enterprise Linux&#xff09;仓库 sudo yum install epel-release安装Software Collections (SCL)仓库&#xff1a;随后&#xff0…

【坑】Spring Boot整合MyBatis,一级缓存失效

一、Spring Boot整合MyBatis&#xff0c;一级缓存失效 1.1、概述 MyBatis一级缓存的作用域是同一个SqlSession&#xff0c;在同一个SqlSession中执行两次相同的查询&#xff0c;第一次执行完毕后&#xff0c;Mybatis会将查询到的数据缓存起来&#xff08;缓存到内存中&#xf…

证件照(兼容H5,APP,小程序)

证件照由uniappuyui开发完成&#xff0c;并同时兼容H5、App、微信小程序、支付宝小程序&#xff0c;其他端暂未测试。 先看部分效果图吧具体可以下方复制链接体验demo 首页代码 <template><view class""><view class"uy-m-x-30 uy-m-b-20"…