解析静态链接
文章目录
- 静态链接
- 空间与地址分配
- 相似段合并
- 虚拟地址分配
- 符号地址确定
- 符号解析与重定位
- 链接器优化
- 重复代码消除
- 函数链接级别
- 静态库
- 静态链接优缺点
静态链接
一组目标文件经过链接器链接后形成的文件即可执行文件,如果没有动态库的加入,那么这个可执行文件被加载后无需再进行重定位操作(符号已经在链接阶段全部得到重定位),这种方式即静态链接,静态链接的过程分为空间与地址分配+符号解析与重定位
空间与地址分配
空间与地址分配阶段链接器需要为各个节分配虚拟地址,分配虚拟地址的第一步就是要把各个目标文件的节进行合并,现代链接器都是采用相似段合并的方式对目标文件的节进行合并,所谓相似节合并,即多个目标文件的代码节合一起,数据节合一起…
相似段合并
链接器扫描所有目标文件各个节的信息,获取其长度,对相似节进行合并,合并完后的节在代码段中称为段。实际上ELF文件中既能称作节(section),也能称作段(segment),但是可执行文件中一般都是称为段,并且有个更专业的术语称为执行视图,而目标文件中的节称为链接视图

虚拟地址分配
//a.c
extern int shared;
int main(){int a=0;swap(&a,&shared);return 0;
}
//b.c
int shared=1;
void swap(int* a,int* b){*a^=*b=*a^=*b;
}
观察2个源文件的目标文件节信息

只需要关注红框选中的三个字段,size和file off为节的大小和在目标文件中偏移量,而VMA是虚拟地址,很明显0地址是无效的,它们其实都还没有被分配虚拟地址,这很正常,因为它们只是目标文件,是不能被执行的,也就没有必要分配什么虚拟地址了,但是由它们静态链接所产生的可执行文件具有有效的虚拟地址

合并后段大小不严格等于目标文件中对应的节大小之和是因为链接过程中还会添加一些额外信息
符号地址确定
目标文件中的各个符号都有相对于节起始位置的偏移量,这个偏移量很重要,符号地址的确定依赖它,对于一个符号来说,它在目标文件中的地址和在可执行文件中的地址是不一样的,链接后这些符号的绝对地址一定会发生变化,为了后续符号解析与重定位可以正常进行,就需要确定符号在可执行文件中的地址,如何确定就是通过这个不变的偏移量(符号地址再怎么变化,它相对于所在节的偏移量是始终不会发生改变的,链接器不会把一个节拆开)

符号解析与重定位
这一步是静态链接的核心步骤,基本上所有的链接错误都是发生在这个阶段,因为该阶段链接器的工作是确定外部符号引用的绝对地址,如果存在需要重定位但是找不到其定义的符号,就直接报错。
重定位工作之前,链接器必须知道可执行文件有哪些符号,哪些符号是需要被重定位的,因此链接器需要借助可执行文件中的全局符号表和全局重定位表,这2张表由是多个目标文件的符号表和重定位表合并而来的,因此可执行文件中的符号表和重定位表由第一步空间与地址分配完成

对于没有经过重定位的目标文件来说,那些外部符号的符号值是没有意义的

链接器将所有的外部符号进行重定位后

经过重定位后CPU就可以通过这个有效的操作数进行相对寻址正确的访问数据和执行函数
链接器优化
重复代码消除
//template.h
template<typename T>T add(T x,T y){return x+y;
}
//a.cc
int main(){add(1,2);return 0;
}
//b.cc
int ADD(int x,int y){return add(x,y);
}
C++中引入了模板,一个模板函数可能被多个源文件所实例化,这会造成重复的代码,例如a.cc和b.cc实例化出的函数都是int add(int,int),链接器会对其进行合并,减少不必要的空间浪费(可执行文件中的代码段只有一份int add(int,int))
更加专业的解释
- 编译器在每个翻译单元中生成模板函数的实例
- 链接器在链接这些对象文件时,会注意到多个相同的函数实例(例如 int add(int, int)),但不会报错,因为它会自动选择其中一个实例,忽略其他重复的实例(前提是定义在头文件中,这样编译器才能实例化)
- 这种行为是由C++标准规定的,称为“外部链接”的模板实例化
模板请不要声明和定义分离,这会造成链接错误
函数链接级别
目标文件中所定义的函数不一定在可执行文件中都会被使用,如果无脑地将所有函数全都放入可执行文件的代码段,这会造成无端的空间浪费,链接器引入了人函数链接级别的概念来优化,简单来说就是只把可执行文件中用到的函数写入可执行文件的代码段,不会用到的那些函数定义丢弃
静态库
静态库即一组目标文件的集合,Linux下通过ar命令对一组目标文件进行打包
ar -rc libmine.a a.o b.o
通过静态库链接可以简化命令行,链接器会在链接过程中从静态库中寻找所需要的数据或函数定义
gcc/g++在链接时默认采用动态链接,显示的静态链接需要添加-static选项
静态链接优缺点
优点
- 过程较为简单,一旦成功生成可执行文件后,就可以直接运行,并且不会有库依赖问题
缺点
- 可执行文件很大,因为静态链接的可执行文件将所有目标文件都进行合并;多个可执行文件可能静态链接了相同的库,但是它们运行时无法共享代码段(即使代码段是一样的),这会造成内存中存在多份一样的代码
- 升级维护困难,静态库的任何更新操作需要重新编译链接生成新的可执行文件
————————————————————————————————————
相关文章:
解析静态链接
文章目录 静态链接空间与地址分配相似段合并虚拟地址分配符号地址确定 符号解析与重定位链接器优化重复代码消除函数链接级别 静态库静态链接优缺点 静态链接 一组目标文件经过链接器链接后形成的文件即可执行文件,如果没有动态库的加入,那么这个可执行…...
前端基础-html-注册界面
(200粉啦,感谢大家的关注~ 一起加油吧~) 浅浅分享下作业,大佬轻喷~ 网页最终效果: 详细代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…...
量子电路的实现 基于ibm的qiskit
量子计算的物理实现 量子计算的实现有几种方式,最常用的就是超导量子计算机,它的量子处理器是用超导传输量子比特构建的,它是由一个约瑟夫森结和一个并联的电容器组成的电路。约瑟夫森结是一种非线性电感,由两层重叠的超导…...
关于谷歌浏览器debug模式不进断点问题解决方案
第一步.浏览器F12弹出调试者模式 第二步.点击设置齿轮,找到Ignore List,将node_model取消勾选,关闭浏览器,重新打开就进断点了...
制造行业实践|悠进电装基于超融合完成信息化改造, 保障业务系统 7/24 长跑
当一辆汽车在路上奔驰时,确保车内各种电气信号正常传递和电力供给的关键是什么?正是那不起眼却功不可没的汽车线束。这些精密编织的电线网络,犹如汽车的“神经网络”和“动脉血管”,在传递电气信号、数据的同时,源源不…...
如何学习C++游戏开发
学习C游戏开发是一个涉及多个领域的复杂过程,包括编程、游戏设计、图形学等。 1. **学习C基础**: - 掌握C的基本语法和面向对象编程。 - 学习C标准库,特别是STL(标准模板库)。 2. **理解游戏开发概念**…...
计算网络信号
题目描述: 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。注意:网络信号可以绕过阻隔物 array[m][n]的二维数组代表网格地图, array[i][j]0代表i行j列是空旷位置&…...
【Vue 全家桶】6、vue-router 路由(更新中)
目录 相关理解基本路由嵌套路由路由传参编程式路由导航 相关理解 基本路由 嵌套路由 路由传参 编程式路由导航...
解决程序因缺少xinput1_3.dll无法运行的有效方法,有效修复丢失xinput1_3.dll
如果你的电脑在运行某些应用程序或游戏时提示“xinput1_3.dll丢失”或“找不到xinput1_3.dll”的错误消息,那么很可能是因为你的系统中缺少这个重要的DLL文件而导致的问题。那么电脑出现xinput1_3.dll丢失的问题时有哪些方法进行修复呢? 如何确定电脑是否…...
uni-popup 弹出框
:maskClick"false" 是点击空白遮罩处不关闭弹窗 <uni-popup ref"popup" type"center" :maskClick"false"> <div style"width: 80vw;padding: 0.5em;box-sizing: border-box; background-color: #fff; border-…...
Android笔记:Android中Fragment改变主题
在Android中,Fragment使用主题可以通过以下几种方法实现: 1 在onCreateView方法中设置主题: 在onCreateView方法中,可以通过创建一个ContextThemeWrapper来改变Fragment的主题。例如: @Override public View onCreateView(LayoutInflater inflater, ViewGroup co…...
GEE 训练——利用sentinel-2数据计算两栖NDVI前后差异
目录 简介 函数 expression(expression, map) Arguments: Returns: Image 代码 结果 简介 利用sentinel-2数据计算两栖NDVI前后差异 COPERNICUS/S2是欧洲空间局(ESA)的地球观测计划,旨在通过卫星遥感技术提供全球的高分辨率地球观测数据。S2是COPERNICUS地球观测计…...
看电动缸是如何提高农机的自动化水平
电动缸作为一种将电动机的旋转运动转变为推杆的直线往复运动的电力驱动装置,在提升农机自动化水平方面发挥了重要作用。以下详细分析电动缸如何提高农机的自动化水平: 一、电动缸的工作原理与优势 电动缸的工作原理是以电力作为直接动力源,采…...
C++ 并发专题 - 条件变量的使用
一:概述: 在 C 中,条件变量(std::condition_variable)是一种用于线程间同步的机制,主要用于在多线程环境中让一个线程等待某个条件满足后再继续执行。条件变量通常配合互斥锁(std::mutex&#…...
《Essential C++》学习笔记
《Essential C》这本书,是适合从C选手快速过度到C选手的 一本书,下面是个人记录 第一章:基础语法 第一章主要就是C语言基础,这里类似于表达式 数组 条件语句 循环语句,就不多概述了。 :::info vector:可动…...
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
在当今的微服务架构蓬勃发展的时代,配置中心扮演着极为关键的角色,其重要性不言而喻。今天,我们就以 Apollo 为例,聊聊配置中心在微服务架构中的重要意义。 一、微服务架构下的配置管理挑战 随着微服务架构的广泛应用࿰…...
每日OJ题_牛客_春游_贪心+数学_C++_Java
目录 牛客_春游_贪心数学 题目解析 C代码 Java代码 牛客_春游_贪心数学 春游 描述: 盼望着,盼望着,东风来了,春天脚步近了。 值此大好春光,老师组织了同学们出去划船,划船项目收费如下:…...
JavaWeb--Maven
1.初始Maven 1.1介绍 Maven 是一款用于管理和构建Java项目的工具,是Apache旗下的一个开源项目 。 1.2Maven的作用 2.Maven概述 2.1Maven介绍 Apache Maven是一个项目管理和构建工具,它基于项目对象模型(Project Object Model , 简称: POM)的概念&am…...
计算机网络——网络层导论
转发是局部功能——数据平面 路由是全局的功能——控制平面 网卡 网卡,也称为网络适配器,是计算机硬件中的一种设备,主要负责在计算机和网络之间进行数据传输。 一、主要功能 1、数据传输: 发送数据时,网卡将计算机…...
使用 JPA 的 `save()` 方法更新数据库中的数据
在开发基于 JPA(Java Persistence API)的应用时,数据持久化操作中的常见问题是执行 save() 方法后数据库中的数据没有更新。本文将详细介绍 JPA 的 save() 方法如何工作、其可能出现的问题,以及如何解决这些问题,以确保…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
