C++编译链接

我们在编译器里面编写一段代码,点击一个键轻而易举就会生成结果,那么大家有没有想过,编译器是如何做的可以让这么一段代码运行起来的,内部是如何实现的,那么今天我们就来看看。

流程如下:

源代码-->预处理-->编译-->汇编-->链接-->生成可执行文件

预处理阶段:主要做的就是删除注释,宏替换,处理预处理指令(#include<>...)在此阶段生成了.i文件

编译阶段:进程词法分析,语法分析,语义分析以及代码优化,在此阶段生成.s文件

汇编阶段:生成目标文件(.o/.obj)汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。在最终的目标文件中除了拥有自己的数据和二进制代码之外,还要至少提供2个表:未解决符号表和导出符号表,分别告诉链接器自己需要什么和能够提供什么。编译器把一个cpp编译为目标文件的时候,除了要在目标文件里写入cpp里包含的数据和代码,还要至少提供3个表:未解决符号表,导出符号表和地址重定向表。 未解决符号表提供了所有在该编译单元里引用但是定义并不在本编译单元里的符号及其出现的地址。 导出符号表提供了本编译单元具有定义,并且愿意提供给其他编译单元使用的符号及其地址。地址重定向表提供了本编译单元所有对自身地址的引用的记录。

链接阶段:合并段,调整段地址偏移,符号重定位

程序最终执行是被加载到虚拟内存上的,下面我们来看看虚拟内存的划分:


.text:指令段,顾名思义就是用来存放指令的

.data和.bss都是数据段,用来存放数据的,只不过存放的数据有所区别,.data用来存放已初始化且不为0的数据,.bss用来存放全局的未初始化或初始化为0的数据。

下面给出一个例子,我们来看看它们都是属于哪个段的。


我们看到全局变量gdata3是属于comment段的,这是为什么呢?

这就引出了又一个问题,在C++大工程里面有两个文件,两个文件中都有x的声明则会出现编译错误,在C中可以,因为在C语言中有强弱类型之分。

强类型:已初始化的数据

弱类型:未初始化的数据

强弱类型之间选择标准:

①如果同一个x的两个定义都是强类型,那么错误类型为“重定义”

②如果一个是强类型另一个是弱类型那么选择强类型

③如果两个类型都是弱类型,那么比较两个弱类型所占字节空间大小,谁大选谁

④如果两个都是弱类型且字节数相等,则看编译器选择

弱类型存在comment中。

.bss节省的是文件的空间而不是虚拟内存空间。常量字符串存放在只读数据段(rodata)

链接:

①合并所有目标文件的段,调整段偏移量和段长度,合并符号表

②符号解析,目标文件中所有对符号引用的地方都要找到符号定义的地方

③空间与地址分配(虚拟地址空间)

④符号重定位

程序的运行:

①创建虚拟地址空间到物理内的映射(创建内核地址映射结构体),创建页目录和页表

②加载代码和数据段

③把可执行文件的入口地址写到CPU的PC寄存器里面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值