C++的编译流程

C/C++的编译流程

编译流程分为四个阶段:预处理、编译、汇编、链接

Linux系统下g++编译为例:

通过g++的选项可以查看过程中的每一步

C++的编译流程_第1张图片

预处理: 处理一些#号定义的命令或语句(如#define、#include、#ifdef等),生成.i文件

编译:进行词法分析、语法分析和语义分析等,生成.s的汇编文件

汇编:将对应的汇编指令翻译成机器指令,生成二进制.o目标文件

链接:链接分为两种

  • 静态链接

​ 在链接期,将静态链接库中的内容直接装填到可执行程序中。

​ 在程序执行时,这些代码都会被装入该进程的虚拟地址空间中。

  • 动态链接

​ 在链接期,只在可执行程序中记录与动态链接库中共享对象的映射信息。

​ 在程序执行时,动态链接库的全部内容被映射到该进程的虚拟地址空间。其本质就是将链接的过程推迟到运行时处理


扩展:

1、 为什么要有静态链接?

​ 在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个.c文件会形成一个.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接

由很多目标文件进行链接形成的是静态库,反之静态库也可以简单地看成是一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件

2、 静态链接的优缺点:

缺点:

  • 浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,如果运行多个程序并且这些程序都对同一个目标文件有依赖,那么目标文件在内存中就会存在多个副本;

  • 更新困难,因为每当一个依赖文件的代码修改了,这个时候就需要全部重新编译链接形成新的可执行程序。

优点:

  • 运行速度快并且不依赖外部环境,因为在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。

C++的编译流程_第2张图片

注意: 我们知道,链接器在链接静态链接库的时候是以目标文件为单位的。比如我们引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中。由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中。

3、 为什么要有动态链接?

​ 为了解决静态链接中提到的两个问题,一方面是空间浪费,另外一方面是更新困难。

​ 流程简介:

​ 假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接.

4、 动态链接的优缺点:
优点:

  • 节约内存: 即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副本,而是这多个程序在执行时共享同一份副本;

  • 更新方便: 更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍。当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标。

缺点:

  • 性能略差: 因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失。
  • 依赖外部环境: 因为把链接推迟到了程序运行时,所以要保证程序运行时外部的库存在且内容正确无误。

C++的编译流程_第3张图片

参考:https://www.cnblogs.com/cyyljw/p/10949660.html

2022/09/24

你可能感兴趣的:(C++,c++,开发语言,c语言)