我们在进行C/C++编译的时候一般要经过四个阶段:预处理(进行宏替换,头文件展开,去注释,条件编译等)——>编译(生成汇编,也就是C语言转换成汇编语言)——>汇编(生成机器可识别代码)——>链接(生成可执行文件或库文件)。
gdb则是一个调试器,用来debug的。
目录
gcc编译过程
概念:gcc就是在Linux编译C语言的编译器,以上我们已经学习了编译的过程有四个,那么他们分别在Linux是如何进行的呢?下面让我们来学习一下吧!
预处理
我们使用-E选项使test.c预处理并且使用-o选项将预处理过的文件存放到test.i中。
具体操作:
查看test.i与test.c
编译
我们使用-E选项使刚刚预处理过的test.i编译并且使用-o选项将编译过的文件存放到test.s中。
具体操作:
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查 无误后,gcc 把代码翻译成汇编语言。
汇编
我们使用-c选项使刚刚编译过的test.s的汇编文件转化为二进制目标文件并且使用-o选项将编译过的文件存放到test.o中。
具体操作:
汇编阶段的工作是将编译产生的汇编文件转化为
.o
二进制目标文件。.o
文件就是VS编译器下的.obj
文件。
但是由于test.o是二进制文件,所以vim打开是乱码。
可以用 od 文件名 查看二进制文件
链接
链接的主要任务就是将生成的各个.o
文件以及库文件进行链接,生成可执行文件。
执行gcc test.c -o test
具体操作:
链接生成的test文件也是二进制文件。
g++简单叙述
其他功能与gcc差不多,只不过g++是编译C++用的,并且注意g++所能识别的C++文件的文件名后缀为.cpp或.cc 等
总结
我们上述是利用Linus把我们在C语言阶段就熟知的四个阶段给展开进行处理和理解,那么如果我们每次不加-o选项那么默认生成a.out文件。并且我们可以对这几个过程的任何一个过程直接进行:
gcc 文件名 -o test 就可以直接生成 可执行文件,也就是不加任何的选项。
动态库与静态库
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以.a为后缀。
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。gcc 在编译时默认使用动态库。
使用file指令进行查看链接类型,使用ldd指令查看动态链接的可执行文件所依赖的库:
默认采用的是动态链接,但如果我们需要使用静态链接,在后面带上-static选项即可:
若没有安装静态库可以使用以下命令进行安装:
sudo yum install glibc-static
sudo yum install libstdc++-static
调试器gdb
前言
- 程序的发布方式有两种,debug模式和release模式
- Linux gcc/g++出来的二进制程序,默认是release模式
- 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
调试前的准备
- gdb 文件名 进入调试
- 文件必须是debug版本
- 调试方法与vs类似只不过从图形界面变换成了命令行
调试指令
我们这里只演示一部分重要的指令。
run/r:运行代码(启动调试)
list/l n:显示从n行开始的源代码,每次显示10行,若n未给出则默认从上次的位置向下显示。
next/n:逐过程调试(不进入函数)
step/s:逐语句调试(进入函数)
break/b n:在第n行设置断点
info b: 显示已打断点的情况
打断点:
删除断点:
关闭与打开断点:
bt:查看调用堆栈
set var:改变调试过程中变量的值
display 变量名 或者 display &变量名:查看值和地址
undisplay 行号:不让某行常显示
finish:提前结束函数
还有一些指令这里不一一演示。
gdb调试指令总结:
- list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list/l 函数名:列出某个函数的源代码。
- r或run:运行程序。
- n 或 next:单条执行。
- s或step:进入函数调用
- break(b) 行号:在某一行设置断点
- break 函数名:在某个函数开头设置断点
- info break :查看断点信息。
- finish:执行到当前函数返回,然后挺下来等待命令
- print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
- p 变量:打印变量值。
- set var:修改变量的值
- continue(或c):从当前位置开始连续而非单步执行程序
- run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- info(或i) breakpoints:参看当前设置了哪些断点
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay:取消对先前设置的那些变量的跟踪
- until X行号:跳至X行 breaktrace(或bt):查看各级函数调用及参数
- info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb