iOS--动静态库

news2024/11/24 10:05:08

文章目录

  • 认识动静态库
    • 静态库
    • 动态库
    • 静态的打包
    • 静态库的使用
    • 动态库的打包
    • 动态库的使用

动静态库的本质就是可执行程序的"半成品"。

需要完成一个可执行程序需要经历以下四个步骤:

预处理:完成头文件的展开,去掉注释,宏替换,条件编译等,最终形成***.i文件
编译:完成语法分析,词法分析,语义分析,符号汇总等,检查无误后将代码翻译成汇编指令,最终形成***.s文件
汇编:将汇编指令转换成二进制指令,最终形成***.o文件
链接:将生成的各个***.o文件进行链接,最终形成可执行程序
例如,用test1.c,test2.c以及main1.c形成可执行文件,需要先得到各个文件的目标文test1.o,test2.o以及main1.o,然后将这些目标文件链接起来,最终形成一个可执行程序。
在这里插入图片描述
对于可能频繁用到的源文件,比如这里的test1.c,test2.c,可以将他们的目标文件test1.o,test2.o进行打包,之后需要用到这两个目标文件就可以直接链接这个包当中的目标文件即可,上面的打包就可以称为一个库。库的本质就是一堆***.O集合,库的文件当中并不包含主函数而只是包含了大量写好的方法以供调用,因此,我们说动静态库是可执行程序的"半成品".

认识动静态库

在这里插入图片描述
可以看到,实际上libc-2.17.so就是一个共享的目标文件库,准确来说,这还是一个动态库。说一下:

  • 在Linux中,以.so为后缀的是动态库,以.a为后缀的是静态库。
  • 在Windows中,以.dll为后缀的是动态库,以.lib为后缀的是静态库
  • 这里的libc.so.6实际上就是C动态库,库的名字就是,去掉前缀lib,再去掉后缀**.so或.a**及其后面的版本。

而g++编译器一般都是默认是动态链接的,若想进行静态链接,可以携带一个 —static
在这里插入图片描述
此时生产的可执行程序就是静态链接了,可以明显观察到静态链接生成的可执行程序文件的大小,要比动态的要大的多。主要原因下面详细介绍。

静态库

Linux下,以.a为后缀的文件。程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候不再需要静态库。本质是在编译时把静态库中的代码复制到进程的代码中。因此使用静态库生成的可执行程序要比一般的程序大。

优点:程序运行的时候不再需要静态库
缺点:生成的可执行程序较大。如果多个使用静态链接生成的程序同时运行会占用大量的内存空间

动态库

Linux下,以.so为后缀的文件。程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。一个动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

在可执行文件开始运行前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程叫做动态链接。动态库在多个程序间共享,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份动态库被调用到该库的所有进程共用,节省了内存和磁盘空间。
在这里插入图片描述

  • **优点:*节省磁盘空间,且多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码
  • 缺点:必须依赖动态库,否则无法运行

静态的打包

本质就是将代码编译成.o的二进制文件,然后进行打包。

为了更好的演示这个过程,创建add.c,add.h,sub.c和sub.h四个文件,内容如下所示:

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

第一步:将所有源文件生成对应的目标文件
第二步:使用ar命令将所有目标文件打包为静态库
ar命令是gnu的归档工具,常用于将目标文件打包为静态库,下面我们使用ar命令的**-r选项和-c**选项进行打包。

  • -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件
  • -c(create):建立静态库文件。
  • 在这里插入图片描述
    第三步:将头文件和生成的静态库组织起来
    当我们把自己的库给别人用的时候,实际上需要给别人两个文件夹,一个文件夹下面放的是一堆头文件的集合,另一个文件夹下面放的是所有库文件

因此,在这里我们可以将add.h和sub.h这两个头文件放到一个名为Include的目录下,将生成的静态库文件libmymath.a放到一个名为lib的目录下,然后将这两个目录放到myliba下,此时就可以将myliba给别人使用了。
在这里插入图片描述

静态库的使用

创建源文件main.c,编写下面这边简单的程序尝试使用我们打包好的静态库。

#include <stdio.h>
#include <add.h>
#include<sub.h>
int main()
{
	int x = 20;
	int y = 10;
	int z = my_add(x, y);
    int q=my_sub(x,y);
	printf("%d + %d = %d\n", x, y, z);
    printf("%d+%d=%d\n",x,y,q);
	return 0;
}

经过调整后目录下只有main.c和我们刚刚打包好的静态库。
在这里插入图片描述
此时使用gcc编译main.c生成可执行程序时需要携带三个选项:

  • -I:指定头文件搜索路径
  • -L: 指定库文件搜索路径
  • -l: 指明需要链接库文件路径下的哪一个库
  • 具体操作如下:
  • 在这里插入图片描述
  • 因为编译器不知道你所包含的头文件add.h在哪里,所以需要指定头文件的搜索路径。
    因为头文件add.h当中只有my_add函数声明,并没有该函数的定义,所以还需要指定所要链接库文件的搜索路径。
    实际中,在库文件的Lib目录下可能会有大量的库文件,因此我们需要指明需要链接库文件路径下的哪一个库,库文件名需要去掉前缀lib,再去掉后缀.so或者.a以及后面的版本号,剩下的就是这个库的真正名字。
    为什么之前使用gcc编译的时候没有指明过库的名字?
    因为我们使用的gcc编译的是C语言,而gcc就是用来编译C程序的,所以gcc编译的时候默认就找的是C库,但此时我们要链接的是哪一个库编译器是不知道的,因此我们需要使用选项,指明需要链接库文件路径下的哪一个库。

动态库的打包

动态库的打包相对于静态库来说有一点点差别,但大致相同,还是以上面的四个文件为例子:
第一步:让所有源文件生成对应的目标文件
此时用源文件生成目标文件时需要携带**-fPIC**选项:
在这里插入图片描述
说明:

  • -fPIC:产生位置无关码

  • -fPIC作用域编译阶段,告诉编译器产生于位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时, 在内存的位置不是固定的。

  • 如果不加-fPIC选项,则加载.so文件的代码段时,代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成了每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的拷贝,并且每个拷贝都不一样,取决于这个.so文件代码段和数据段内存映射的位置。

  • 不加-fPIC编译出来的.so是要在加载时根据加载到的位置再次重定位的,因为它里面的代码BBS位置无关代码。如果该.so文件被多个应用程序共同使用,那么它们必须每个程序维护一份.so的代码副本(因为.so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)。

  • 我们总是用-fPIC来生成.so,但从来不用-fPIC来生成.a,但是.so一样可以不用-fPIC选项进行编译,只是这样的.so必须要在加载到用户程序的地址空间时重定向所有表目。

    第二步:使用-shared选项将所有目标文件打包成动态库

    与生成静态库不同的是,生成动态库时我们不必使用ar命令,只需使用gcc的-shared选项即可。
    在这里插入图片描述
    第三步: 将头文件和生成的动态库组织起来

与生成静态库时一样,为了方便别人使用,在这里可以将add.h和sub.h这两个头文件放到一个名为include的目录下,将生成的的动态库文件libcal.so放在一个名为lib的目录下,然后将这两个目录都放在mlib下。
在这里插入图片描述

动态库的使用

使用main.c来演示动态库的使用和我们刚打包好的动态库
在这里插入图片描述
使用该动态库的方法与刚才我们使用静态库的方法一样,我们既可以用-I,-L,-l这三个选项来生成可执行程序,也可以先将头文件和库文件拷贝到系统目录下,然后仅使用-l选项指明需要链接的库名字来生成可执行程序。下面仅以第一种方法为例进行演示。
在这里插入图片描述
与静态库不同的是,这里无法直接运行。

需要注意,这里使用-I,-L,-l这三个选项都是在编译期间告诉编译器我们使用的头文件和库文件在哪里以及是谁,但是当生成的可执行程序生成后就与编译器没有关系了,此后该可执行程序运行起来后,操作系统找不到该可执行程序所依赖的动态库。
在这里插入图片描述
既然找不到我们的库文件,那么我们直接将库文件拷贝到系统共享的库路径下,这样一来系统就能找到对应的库文件了。
在这里插入图片描述

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

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

相关文章

微信小程序学习笔记(五)——优化

下拉刷新后主动关闭 Page({onPullDownRefresh: function() {// ...wx.stopPullDownRefresh()} })在发起请求时设置 loading&#xff0c;请求结束后关闭 Page({onLoad: function(options) {wx.showLoading({title: 数据加载中...}) // 展示 loadingwx.request({// ...complete: …

leetcode每日一练-第206题-反转链表

一、思路 迭代 二、解题方法 以输入为 1 -> 2 -> 3 -> 4 -> 5 的链表为例 三、code class Solution { public:ListNode* reverseList(ListNode* head) {ListNode* prevnullptr;//反转后的链表ListNode* currhead;//当前更新的原有链表while(curr)//原有链表无值…

【大模型】更强的 LLaMA2 来了,开源可商用、与 ChatGPT 齐平

【大模型】可商用且更强的 LLaMA2 来了 LLaMA2 简介论文GitHubhuggingface模型列表训练数据训练信息模型信息 许可证参考 LLaMA2 简介 2023年7月19日&#xff1a;Meta 发布开源可商用模型 Llama 2。 Llama 2是一个预训练和微调的生成文本模型的集合&#xff0c;其规模从70亿到…

中间件安全-CVE漏洞复现-Weblogic+JBoss+GlassFish

服务攻防测试流程&#xff1a; 使用vulfocus靶场&#xff1a; 案例演示&#xff1a;中间件-Weblogic-工具梭哈 探针默认端口&#xff1a;7001&#xff0c;Weblogic是Oracle公司推出的J2EE应用服务器 使用vulfocus靶场复现漏洞 漏洞&#xff1a;weblogic-cve_2020_14883 启动环…

自然语言处理:赋予AI理解和交流的能力

文章目录 &#x1f340;引言&#x1f340;NLP的定义与重要性&#x1f340;NLP的应用领域&#x1f340;学好自然语言处理需要掌握以下知识&#x1f340;GPT和自然语言处理&#x1f340;总结 &#x1f340;引言 自然语言处理&#xff08;Natural Language Processing&#xff0c;…

Visual Studio创建Web项目时候报错- 找不到“2.0.1“版本的程序包”解决方法

问题描述 在今天我开始想做一个ASP.Net Web 项目时&#xff0c;在创建项目的时候突然报下面这个错&#xff0c;也是试了很多方法&#xff0c;比如卸载重新安装&#xff0c;安装更高版本&#xff0c;我之前用的是2019版本&#xff0c;后面下载了2022的&#xff0c;又出现了新的…

python与深度学习(三):ANN和fashion_mnist

目录 1. 说明2. fashion_mnist实战2.1 导入相关库2.2 加载数据2.3 数据预处理2.4 数据处理2.5 构建网络模型2.6 模型编译2.7 模型训练2.8 模型保存2.9 模型评价2.10 模型测试2.11 模型训练结果的可视化 3. fashion_mnist的ANN模型可视化结果图4. 完整代码 1. 说明 本篇文章是A…

(202307)wonderful-sql:环境搭建(ubuntu 22.04 + mysql 8.0 + workbench/dbeavar,免密码-不建议免哈)

前言 能够再次参加datawhale组织的开源学习是十分兴奋的&#xff0c;看到datawhale能够越办越好我也是由衷地感到高兴。 这次参加的是mysql的学习&#xff0c;我知道这样短期的学习不会对我的能力造成多么大的提升&#xff0c;但是相信经过这次学习&#xff0c;我又将被datawh…

Kubernetes中Pod的扩缩容介绍

Kubernetes中Pod的扩缩容介绍 在实际生产系统中&#xff0c;我们经常会遇到某个服务需要扩容的场景&#xff0c;也可能会遇到由于资源紧张或者工作负载降低而需 要减少服务实例数量的场景。此时可以利用 Deployment/RC 的 Scale 机制来完成这些工作。 Kubernetes 对 Pod 的扩…

java代码审计1之环境搭建

文章目录 1、安装jdk2、配置tomcat3、配置maven3.1、配置环境变量3.2、配置源和maven配置文件 4、idea4.1、配置maven4.2、新建web项目4.3、遇到的问题(弹出404页面) 之前的文章&#xff0c; https://blog.csdn.net/weixin_43970718/article/details/121929434 https://blog.…

(全网最详细!)mysql、redis 、RabbitMQ只能本机访问,怎么改?

如果只能本机访问&#xff0c;怎么改? 一、mysql - 改my.ini 刷脚本 bind-address0.0.0.0 然后重启一下mysql服务 任务管理器-关掉mysql 搜索 计算机管理-重启mysql服务 然后 打开查询&#xff0c;并选择mysql数据&#xff0c;输入这个sql语句&#xff0c;点击运行 sele…

POC!VMWare RCE CVE-2023-20887

漏洞简介 VMWare Aria Operations for Networks (vRealize Network Insight) 在通过 Apache Thrift RPC 接口接受用户输入时容易受到命令注入的攻击。此漏洞允许远程未经身份验证的攻击者以 root 用户身份在底层操作系统上执行任意命令。RPC 接口受可以绕过的反向代理保护。VM…

vue3+vue-router4:报错Uncaught (in promise) Error: Invalid navigation guard

报错图示&#xff1a; Error: Invalid navigation guard Uncaught (in promise) Error: Invalid navigation guard 错误影响描述&#xff1a; 配置开发、测试、生产时候&#xff0c;因为是公众号&#xff0c;所以想在开发环境下免鉴权&#xff0c;不走微信获取openid接口&a…

PHP要怎么学--【思维导图知识范围】

强撸项目 总目录在此 专辑工作量PHP登陆/php登录–【强撸项目】难度★✫✰✰✰PHP注册/登录/发邮件–【强撸项目】★★★✫✰PHP在线相册–【强撸项目】★★★★✫–【强撸项目】––【强撸项目】––––– 文章目录 本系列校训学习资源的选择环境的问题本人推荐 PHP视频的知…

C语言-分支语句和循环

目录 【1】字符输入输出 【2】C语言下的垃圾字符回收 【3】分支语句 【4】循环 练习&#xff1a; 【1】字符输入输出 按字符的输入输出 int getchar(void); 功能&#xff1a;从终端输入一个字符 参数&#xff1a;无 返回值&#xff1a;输入字符的ASCII值int putchar(int…

pandas常用方法

一、提要 pandas对于处理表格类数据来说是非常方便的模块&#xff0c;同时也是做数据分析绕不开的第三方库。这里将工作中常用到的各种处理方法记录下来二、常用方法 接下来的以 df 表示我们要处理的 dataframe 表格数据 1、取值 # 循环遍历取值 for i in range(len(df)):y…

Spring Cloud之Gateway网关应⽤

使⽤⽹关对静态化微服务进⾏代理&#xff08;添加在它的上游&#xff0c;相当于隐藏了具体微服务的信息&#xff0c;对外暴露的是⽹关&#xff09;。 1. 右键⽗⼯程【 yx-parent 】选择【 New 】 - 【 Module 】选项&#xff0c;然后选择创建【 Maven 】类型项⽬&#xff08;不…

以高质量产业载体为底色,绘就珠海高新区产业发展新图景

【作者】珠海高新招商 “珠海高新招商”以招商运营为核心&#xff0c;聚焦珠海工业园区、珠海5.0产业园等招商引资工作&#xff0c;依托专业的招商团队和丰富的创新资源&#xff0c;为企业提供产业园入驻、平台搭建、产业政策咨询、科技服务等全流程专业服务。推动高新区招商引…

17 数组动态初始化

动态初始化&#xff1a;初始化时只指定数组长度&#xff0c;由系统为数组分配初始值。 格式&#xff1a;数据类型[] 数组名 new 数据类型[数组长度] package demo;public class Demo11 {public static void main(String[] args) {// 动态初始化数组&#xff1a;数据类型[] 数…

日撸java三百行day77-80

文章目录 说明GUI1. GUI 总体布局2. GUI 代码理解2.1 对话框相关控件2.1.1 ApplicationShowdown.java&#xff08;关闭应用程序&#xff09;2.1.2 DialogCloser.java&#xff08;关闭对话框&#xff09;2.1.3 ErrorDialog.java&#xff08;显示错误信息&#xff09;2.1.4 HelpD…