C++文件需要经历编译和链接两大步骤才能生成可执行文件。
编译
会生成二进制可重定位的目标文件,其中的重定位指的是符号重定位,发生了链接阶段。
二进制可重定位的目标文件:也就是我们通常所说的.o,.obj文件。
二进制文件构成:二进制文件就是.o文件,其中的内容除了elf文件头,还由各个段组成,有些段和内存空间个段可以匹配,比如.text,.data.,.bss段。objdump -s 和readelf -S是一个用于显示二进制文件的内容的命令。
编译过程:分为预编译、编译、汇编三个阶段,然后每个.cpp会生成.o文件。
预编译:处理#开头的命令,除了#program。
编译:做语法、语义等分析,以及代码优化,可以在g++的时候指定优化级别。
汇编:生成相应平台的汇编代码,比如X86体系的汇编或AT&T的汇编。
链接
会生成可执行文件。
链接:编译完成的所有.o文件 + 静态库文件。
符号表:符号表是目标文件(如 .o 文件)的一个重要组成部分。符号可以是函数(包括main函数)、全局变量、静态变量和局部变量等。符号表提供了这些符号的名称、地址、类型、所处的段、local或global属性等信息。可以用objdump -t XX.cpp命令查看cpp的符号表。
链接过程:1、所有.o文件断的合并,其中符号表合并后进行符号解析。2、符号的重定位(链接的核心)。链接完成后会生成.exe或其他类型的可执行文件。
链接过程中的合并:把各个.o文件的段进行合并。符号解析的时候,如果有符号找不到定义的地方,那么会报错。如果有全局变量重名并且不同类型,那么也会合并失败,报重定义错误。
符号的重定位:合并成功之后,解析符号的时候给所有的符号分配虚拟地址。程序运行的时候,一个程序占用一个进程,一个进程对应一个虚拟内存空间,符号也会根据地址相应分配。