1. C++知识面试版_基础
1.1 编译过程
如上所示,一个c源文件会先经过预处理,将头文件展开、宏替换和去注释;然后经过编译器生成汇编文件,再有汇编器生成二进制文件,最后再经过链接器将函数库中相应的代码组合到目标文件
预处理:预处理器会扫描源代码文件,根据以“#”开头的预处理指令执行一些文本替换和文件包含操作。例如,预处理器会把所有的#include指令替换为对应的头文件内容,并将定义的宏展开。生成.i
文件
编译:编译器将经过预处理的源代码文件翻译成汇编代码,这是一种与具体机器体系结构相关的低级代码。生成.s
文件
汇编:汇编器将汇编代码转化为机器码,并生成一个目标文件(.obj 或 .o)。目标文件包含机器指令和一些元数据,如符号表和重定位信息。生成二进制.o
文件
- 链接:链接器将目标文件与系统库和其他目标文件链接在一起,生成可执行文件。链接器主要完成两个任务:解析符号引用和地址重定位。
- 符号解析:每个符号对应一个函数、一个全局变量或一个静态变量,符号解析的目的就是将每个符号引用正好和一个符号定义关联起来。那么当然在不同目标文件中引用的同一全局变量或函数,链接器需要将其解析为同一个实体。
- 地址重定位指的是在链接过程中,需要将不同目标文件中的函数和变量的地址进行调整,使得它们在最终的可执行文件中能够正确地链接到一起。生成可执行文件
1.2 静态链接和动态链接
1.2.1 静态链接:
链接器将目标文件和库文件的代码和数据全部拷贝到可执行文件中,形成一个独立的、包含所有必需代码和数据的可执行文件。在运行时,可执行文件不需要依赖外部库文件,所有需要的代码和数据都已经包含在可执行文件中
- 优点:对运行环境的依赖性较小,具有较好的兼容性,方便分发和部署,不需要外部依赖
- 缺点:生成的程序比较大,需要更多的系统资源,在装入内存时会消耗更多的时间;库函数有了更新,必须重新编译应用程序
1.2.2 动态链接
在动态链接中,库文件的代码和数据被保留在一个独立的文件中,被多个可执行文件共享。在链接时,链接器会将可执行文件中需要的库函数和数据的引用替换为动态链接库的符号表中对应的地址。在运行时,当程序调用一个需要动态链接库中的函数时,操作系统会将对应的库文件加载到内存中,并将调用转向库文件中的函数
- 优点:在需要的时候才会调入对应的资源函数;简化程序的升级;可执行文件小,节省磁盘空间;同时多个可执行文件可以共享同一个库文件,减少了内存占用
- 缺点:依赖动态库,不能独立运行;动态库依赖版本问题严重。如果库文件版本或路径发生变化,可能会导致程序无法正常运行
注:前面我们编写的应用程序大量用到了标准库函数,系统默认采用动态链接的方式进行编译程序,若想采用静态编译,加入-static
参数。
1.2.3 运行是加载和链接共享库