一个C++源文件从文本到可执行文件经历的过程

一个C++源文件从文本到可执行文件经历的过程

此文章来自于 https://blog.csdn.net/daaikuaichuan/article/details/89060957
仅供参考, 我是用来记笔记的。

以"hello world" 程序为例子, 这个程序在编译中是这样执行的,首先执行g++ helloworl.cpp 可以分为四个小步骤,分别是预处理,编译,汇编,和连接,这就像是一个被隐藏的过程,使用者可以通过简单命令即可完成复杂的步骤。

1. 预处理(产生.i 文件, -E)

首先是源代码文件helloworld.cpp和相关的文件预处理成一个.i文件。命令g++ -E helloworld.cpp -o helloworld.i 预处理过程主要处理那些源代码文件中只能够以“#” 开始的预处理指令,主要队则如下:

  • 将所有#define 删除, 并将宏定义展开。
  • 处理#inlude预编译指令, 将被包含的文件插入到预编译指令的位置。这个过程是递归进行的,因为被包含的文件也可能包含其他的文件。
  • 预处理过程会过滤掉/**/和//中的内容。
  • 另外还会添加行号和文件名标识
  • 最后会保留#program编译器指令,因为编译器需要使用他们。
  • 面试题:
    1. #idndef, #ifdef, #endif 的作用? 防止重复包含头文件 2.#include 尖括号和双引号的区别 #include< > , 从标准库中寻找头文件 #include" ", 从当前目录开始寻找头文件。
2. 编译 (产生.s文件, -s)

编译就是将预处理的文件进行一系列的词法分析,语法分析,语义分析,以及优化后产生相应的汇编代码文件,这个过程是程序构建的核心部分,也是复杂的。执行命令:g++ -S helloworld.i -o helloworld.s
可以用vi/vim查看相应汇编代码。在这个过程中有分为6步:词法分析,语法分析,源代码优化,代码生成和目标优化。

3. 汇编 (产生.o或.obj文件, -c)

汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程,即生成目标文件。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件由段组成,通常一个目标文件中至少有两个段:

  • 代码段:该段中所包含的重要是程序的指令。该段一般是可读和可执行的,但一般不可读写
  • 数据段主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。

Unix环境下主要有三种类型的目标文件:

  • 可重定位文件:其中包含有适合于其他目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。
  • 共享的目标文件:这种文件存放了适合于两种上下文里的链接的代码和数据。第一种是链接程序可以把它与其他可重定位文件及共享的目标文件一起处理来创建另一个目标文件;第二种就是动态链接程序将它与另一个可执行文件及其他的共享目标文件结合到一起,创建一个进程映像。
  • 可执行文件:它包含一个可以被操作系统创建一个进程来执行的文件。
    汇编程序生成的实际上是第一种类型的文件,对于后两种还需要其他一些处理方能得到,这个就是链接程序的工作。
4. 链接(产生.out或.exe文件, -o)

链接就是把每个源代码独立的编译,然后按照它们的要求组装起来,链接主要解决的就是源代码之间的相互依赖问题,链接的过程包括地址和空间的分配,符号决议,和重定位等这些步骤。
每个目标文件除了拥有自己的数据和二进制代码,还拥有三个表,未解决符号表,地址重定向表,导出符号表。根据开发人员指定的同库函数的链接方式不同,链接处理可分为两种:

  1. 静态链接/库
    在链接阶段,会将编译生成的目标文件.o与引用到的库文件一起链接打包到可执行文件中,因此对应的链接方式称为静态链接
    静态库可以简单看成一组目标文件(.o/.obj文件的集合),即很多目标文件经过压缩打包后行成的一个文件。
    缺点: 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接到合成一个可执行文件。
    在这里插入图片描述
  2. 动态链接/库
    动态库在程序编译时不会被链接到目标代码中,而是在程序运行时才被载入,不同的程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间良妃问题。动态库在程序运行时才被载入,也解决了静态库对于程序的更新、部署和发布带来的麻烦。用户只需更新动态库即可,增量更新。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值