前言:在上一篇我们简单介绍了yum,vim的一些常用的指令和模式,现在让我们来进一步了解其他的Linux环境基础开发工具gcc/g++,gdb。
首先让我们来初步了解一下本篇的内容:
1. 学习gcc/g++,并能学会如何使用
2. 学习gdb使用,并能进行简单调试
本篇主要内容:
Linux编译器-gcc/g++使用
Linux调试器-gdb使用
1. Linux编译器-gcc/g++
首先,让我们先来分别了解一下彼此在GNU的作用。
gcc: C语言编译器,只能编译C语言
g++: C++编译器,C/C++都可以编译
gcc和g++在执行编译的时候一般有以下四个步骤:
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 链接(生成可执行文件或库文件)
1.1 gcc/g++的使用方法
gcc/g++使用方法如下:
生产的可执行程序a.out
指令:
gcc code.c
自定义可执行程序的名字
指令:
gcc code.c -o 自定义名称
注意:-o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。
让我们来进行一个简单的测试:
如果我们想执行这个程序,我们可以:
指令:
./a.out
注意:必须加上.才表示要在当前目录下找可执行文件。
接下来,让我们深入了解gcc/g++的四个步骤:
预处理阶段,编译阶段,汇编阶段,链接阶段
1.2 预处理
在预处理阶段的主要功能包括:宏定义,头文件展开,条件编译,去注释等
我们直接用指令查看一下:
指令:
gcc -E test.c -o test.i
- -E选项的作用是让gcc/g++在预处理结束后停止编译过程, 生成.i文件
我们直接进入探索。
可以发现,我们写的代码明明只有几行,但是在test.i中,却多出几百行代码,而这些代码就是预处理阶段展开的头文件,去注释,宏替换,条件编译等操作而出现的。
1.3 编译
在汇编阶段,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查
无误后,gcc 把代码翻译成汇编语言。
简而言之就是:将C语言翻译为汇编代码
我们直接用指令查看一下:
指令:
gcc -S test.i -o test.s
- -S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码, 生成.s文件
我们依然直接进入看看
这里面将代码翻译成了汇编语言
注意:我们可以直接使用指令从.c文件变为.s文件
1.4 汇编
在汇编阶段,就是把编译阶段生成的“.s”文件转成目标文件
将汇编代码变成可重定位二进制文件
我们直接用指令查看一下:
指令:
gcc -c test.i -o test.o
- -c得到汇编代码转化为.o的二进制目标代码,形成.o文件
我们还是直接进入看看
我们发现文件里面是乱码,也就是二进制文件
注意:我们可以直接使用指令从.c文件或.i文件变为.o文件
1.5 链接
在完成预处理,编译,汇编后就到了链接阶段,链接的主要任务就是将生成的各个.o文件进行链接,生成可执行程序
.o文件 + 系统库 = 可执行程序
因此这里又涉及到一个重要的概念:函数库
我们直接用指令查看一下:
指令:
gcc test.o -o test
若未自定义文件名称,则为a.out
2. 函数库
函数库一般分为静态库和动态库两种:
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也
就不再需要库文件了。其后缀名一般为.a - 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为.so,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件
我们可以用指令来查看一个可执行程序依赖的库:
指令:
ldd 可执行程序
因此,test可执行程序所依赖的标准库在路径lib64里有一个文件叫libc.so.6
所以链接过程就是将.o文件和动/静态库结合的过程
动态库:
优点:省空间,形成的可执行程序体积较小
缺点:有强依赖性,依赖动态库
静态库:
优点:不依赖动态库,可以独立运行
缺点: 体积太大,浪费资源
Linux和windows下的动静态库命名是不太一样的
我们在编译代码时,默认采用的是动态链接,Linux下绝大多数库都是动态库,如果我们想静态链接:
指令:
gcc test.c -static
下面给大家列举出了gcc的常用选项
4. Linux调试器-gdb使用
首先了解一下程序发布的方式:
程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式
- debug版本:程序本身会加入调试信息,可以进行调试
- release版本:不会添加任何调试信息,是能调试
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
因为在debug版本下,会加入调试信息,所以程序的大小比release版本下的大!
我们想进入gdb模式,我们可以:
指令:
gdb 文件名
我们想退出gdb模式,我们可以:
指令:
ctrl + d
或quit
下面给大家介绍一下常用的gdb指令:
调试:
r或run:运行程序
n 或 next:单条执行
s或step:进入函数调用
until X行号:跳至X行
finish:执行到当前函数返回,然后挺下来等待命令
continue或c:运行到下一个断点处
set var 变量=x:修改变量的值为x
显示:
list/l n:显示从第n行开始的源代码,接着上次的位置往下列,每次列10行
list/l 函数名:列出某个函数的源代码
print/p 变量:打印变量的值
print/p 表达式:打印表达式的值,通过表达式可以修改变量的值
display 变量:跟踪查看一个变量,每次停下来都显示它的值
undisplay 编号:取消指定编号变量的常显示
info/i locals:查看当前栈帧当中局部变量的值
断点:
break/b n:在第n行设置断点
break 函数名:在某个函数开头设置断点
info break/b:查看已打断点信息
delete/d 编号:删除指定编号的断点
disable 编号:禁用指定编号的断点
enable 编号:启用指定编号的断点
Linux调试器-gdb我们就介绍到这里,调试器需要大家多去使用才能更好的理解与记忆
4. 总结
在理解完本篇之后希望各位都能理解gcc/g++的四个步骤,gdb的简单使用方法!
谢谢大家支持本篇到这里就结束了