C++编译链接原理

从底层剖析程序从编译到运行的整个过程

三个阶段

    • 一、编译阶段
    • 二、链接阶段
    • 三、运行阶段

为了方便解释,给出两端示例代码,下面围绕代码进行实验:

//sum.cpp
int gdata = 10;
int sum(int a,int b)
{return a+b;
}
//main.cpp
extern int gdata;
int sum(int ,int);static int stat;int data = 20;int main()
{int a = gdata;int b = data;int ret = sum(a,b);return 0;
}

前两个阶段:
在这里插入图片描述

一、编译阶段

在这里插入图片描述
三件重要的事情:
编译阶段只关注自己模块内的事情
编译阶段不分配虚拟空间地址,无法运行
目标文件由各个段组成

编译阶段的产物是可重定位的二进制目标文件,由各个段组成
在这里插入图片描述
一、符号表(.symtab段)
查看符号表命令:objdump -t main.o
在这里插入图片描述
1.符号表中存储程序产生的符号,如
静态全局变量stat的符号为_ZL4stat ,定义在.bss区域
全局变量data的符号为data,定义在.data区域
主函数main()的符号为main,定义在.text区域
外部变量gdata的符号为gdata,定义为UND,表示符号的引用,不知道在哪里定义
外部函数sum(int,int)的符号为_Z3sumii,定义为UND,表示符号的引用,不知道在哪里定义

2.符号表中可以看到变量的链接属性
l:表示lcoal,符号只能在当前文件可见,内部链接属性
g:表示global,符号可以在所有文件可见,外部链接属性

所以链接的时候链接器只能看见gloal的符号 看不到lcoal的符号
这就解释了静态全局变量/函数 和普通全局变量/函数同名的问题
在多个文件中可以定义名字相同的静态全局变量/函数,因为local属性链接器不可见,但若多个文件中普通的全局变量/函数重名,因为具有global属性,链接的时候符号解析就会冲突

3.编译过程中变量不分配虚拟空间地址
我们查看以下.text段,注意需要带有-g输出调试信息
g++ -c main.cpp -g
objdump -S main.o
在这里插入图片描述观察,编译阶段产生了二进制机器码,但是不分配虚拟空间地址,所以地址先用0替代,即编译阶段指令没法用,需要等链接阶段分配虚拟地址补上地址才有用,这就是目标文件无法运行的原因之一
4.查看目标文件的各个段
命令:readelf -S main.o
在这里插入图片描述

二、链接阶段

在这里插入图片描述

链接所有的编译完成的目标文件(.o)和静态库文件(.a)
链接步骤:
步骤一:
将所有的目标文件的各个段进行合并
main.o的.text段和sum.o的.text段合并
main.o的.data段和sum.o的.data段合并
main.o的.bss和sum.o的.bss段合并
合并后进行符号解析
如链接阶段符号为UND(符号引用)的,都需要找到该符号定义的地方,如果没有找到=符号未定义,找到多个定义=符号重定义
UND 找到定义解析成具体 .text .data ..

步骤二:
符号的重定位(重定向)
符号解析之后,给所有的符号分配虚拟地址空间,成为了可执行文件

验证
使用链接器自己链接::ld -e main sum.o main.o
查看符号表:objdump -t a.out
在这里插入图片描述
可以看到所有符号均有定义的段,无UND符号引用的情况
所有符号均分配了地址(看第一列)

再看看代码段.text
在这里插入图片描述
之前机器码缺少地址的,现在也都补充上了,所以变成了可以运行的二进制机器码(指令)

补充1:
看一下可执行文件的文件头信息
在这里插入图片描述

.text段的信息
在这里插入图片描述
可以发现,可执行文件头记录了程序入口指令地址,所以CPU知道从哪个指令开始执行(这里是main函数作为入口)

补充2:
可执行文件所有的段都和二进制目标文件相同,多了一个programa headers段,用来告诉操作系统,运行这个程序的时候,把哪些内容加载进内存(数据段 指令段),注意:不是所有的段都需要加载进内存的
查看programa headers段:readelf -l a.out
在这里插入图片描述

三、运行阶段

在这里插入图片描述

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

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

相关文章

初始redis:在Ubuntu上安装redis

1.先切换到root用户 使用su命令切换到root 2.使用apt命令来搜索redis相关的软件包 命令:apt search redis 3.下载redis 命令: apt install redis 在Ubuntu 20.04中 ,下载的redis版本是redis5 4.查看redis状态 命令: netst…

Python自动化测试系列[v1.0.0][高效自动化设计]

Python多线程应用于自动化测试 将多线程在测试巧妙地应用,确实会带来很多好处,并且这是充分利用机器资源执行高效率测试很好的方式 # -*- coding: utf-8 -*- import threading from time import ctime import time from selenium import webdriverdef …

LLM 入门与实践(四) Yi 部署与分析

本文截取自20万字的《PyTorch实用教程》(第二版),敬请关注:《Pytorch实用教程》(第二版)无论是零基础入门,还是CV、NLP、LLM项目应用,或是进阶工程化部署落地,在这里都有…

python对象

类 我们目前所学习的对象都是Python内置的对象但是内置对象并不能满足所有的需求,所以我们在开发中经常需要自定义一些对象类,简单理解它就相当于一个图纸。在程序中我们需要根据类来创建对象类就是对象的图纸!我们也称对象是类的实例&#…

JAVA--IO流

一、IO流什么? I/O是Input/output的缩写,用于处理设备之间的数据传输。如读/写文件、网络通讯。 java程序中,对于数据的输入、输出是以流(Stream)的方式进行。 Java.io包下提供了各种流类和接口,用以获取不同种类的数…

ELfK logstash filter模块常用的插件 和ELFK部署

ELK之filter模块常用插件 logstash filter模块常用的插件&#xff1a; filter&#xff1a;表示数据处理层&#xff0c;包括对数据进行格式化处理、数据类型转换、数据过滤等&#xff0c;支持正则表达式 grok 对若干个大文本字段进行再分割成一些小字段 (?<字段名…

【算法篇】KMP算法,一种高效的字符串匹配算法

我们今天了解一个字符串匹配算法-KMP算法&#xff0c;内容难度相对来说较高&#xff0c;建议先收藏再细品&#xff01;&#xff01;&#xff01; KMP算法的基本概念 KMP算法是一种高效的字符串匹配算法&#xff0c;由D.E.Knuth&#xff0c;J.H.Morris和V.R.Pratt提出的&#…

LLMs之gptpdf:gptpdf的简介、安装和使用方法、案例应用之详细攻略

LLMs之gptpdf&#xff1a;gptpdf的简介、安装和使用方法、案例应用之详细攻略 目录 gptpdf的简介 1、处理流程 第一步&#xff0c;使用 PyMuPDF 库&#xff0c;对 PDF 进行解析出所有非文本区域&#xff0c;并做好标记&#xff0c;比如: 第二步&#xff0c;使用视觉大模型&…

MySQL安装时initializing database失败

问题页面&#xff1a; 解决方法&#xff1a; 1.勾选红框中的选项&#xff1a; 2.将下图红框中全部改为英文&#xff1a; 然后一路next就可以了。

cs231n作业1——KNN

参考文章&#xff1a;assignment1——KNN KNN 测试时分别计算测试样本和训练集中的每个样本的距离&#xff0c;然后选取距离最近的k个样本的标签信息来进行分类。 方法1&#xff1a;Two Loops for i in range(num_test):for j in range(num_train):dist X[i, :] - self.X…

vue3使用方式汇总

1、引入iconfont阿里图库图标&#xff1a; 1.1 进入阿里图标网站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加图标&#xff1a; 1.3 下载代码&#xff1a; 1.4 在vue3中配置代码&#xff1a; 将其代码复制到src/assets/fonts/目录下&#xff1…

mp4视频太大怎么压缩不影响画质,mp4文件太大怎么变小且清晰度高

在数字化时代&#xff0c;我们常常面临视频文件过大的问题。尤其是mp4格式的视频&#xff0c;文件大小往往令人望而却步。那么&#xff0c;如何在不影响画质的前提下&#xff0c;有效地压缩mp4视频呢&#xff1f;本文将为您揭秘几种简单实用的压缩技巧。 在分享和存储视频时&am…

Open3D 计算点云的欧式距离

目录 一、概述 1.1欧式距离定义 1.2作用和用途 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2处理后点云 一、概述 在Open3D中&#xff0c;compute_point_cloud_distance函数用于计算两个点云之间的距离。具体来说&#xff0c;它计算的是源点云…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验16 路由信息协议RIP

一、实验目的 1.验证RIP协议的作用&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.验证RIP协议。 四、实验步骤 1.构建网络拓扑 …

【图像处理】Krita 一款开源免费专业图像处理软件分享

软件介绍 Krita 是一款专业级的图像处理软件&#xff0c;适合数字绘画和创作。它不仅支持栅格图像的细致编辑&#xff0c;还提供了强大的矢量图形工具&#xff0c;使得用户可以在同一个平台上完成多种类型的创作工作。同时具备一定的矢量图形编辑功能。Krita 的首要用途是绘画…

黑马点评商户缓存查询作业——Redis中查询商户类型

记录下自己在gpt帮助下完成的第一个需求~~~ 1. ShopTypeController 2. IShopTypeService 3. ShopTypeServiceImpl&#xff08;模仿ShopServiceImpl来写的&#xff09; 一共分为“1.redis中查询缓存”→“2.判断缓存是否存在&#xff0c;存在直接返回”→“3.缓存不存在则去查数…

2-28 基于matlab提取出频域和时域信号的29个特征

基于matlab提取出频域和时域信号的29个特征&#xff0c;主运行文件feature_extraction&#xff0c;fre_statistical_compute和time_statistical_compute分别提取频域和时域的特征&#xff0c;生成的29个特征保存在生成的feature矩阵中。程序已调通&#xff0c;可直接运行。 2-2…

C语言 printf 函数多种输出格式以及占位输出

一、输出格式 在C语言中&#xff0c;printf 函数提供了多种输出格式&#xff0c;用于控制不同类型数据的输出方式。 1.整数输出格式 %d&#xff1a;以十进制形式输出整数。 %o&#xff1a;以八进制形式输出整数&#xff08;无前导0&#xff09;。 %x 或 %X&#xff1a;以十六进…

EAI四个层次服务-系统架构师(二十六)

1、&#xff08;重点&#xff09;系统应用集成提供了4个不同层次服务&#xff0c;最上层服务是&#xff08;&#xff09;服务。 解析: EAI&#xff08;Enterprise Application Integration&#xff09;系统应用集成&#xff0c;相关概念。 实施EAI必须保证&#xff1a;应用程…

星间链路与星地链路

目录 一、星间链路 1.1 层内星间链路&#xff08;Intra-layer ISLs&#xff09; 1.2 层间星间链路&#xff08;Inter-layer ISLs&#xff09; 1.3 实现方式 1.3.1 微波链路 1.3.2 激光链路 二、星地链路 2.1 星地链路的关键特性 2.1.2 Ka信关站 2.1.2 Q/V信关站 2.1…