前言
前些天面试新大陆,因为岗位要求在Linux环境下工作,被问到是否有用gcc、gdb来调试程序,被问懵了。虽然有学过gcc、gdb以及Makefile,但是平常项目调试都是使用IDE下自带调试工具,gcc那些基本没有用过...所以今天来总结一下,补补课。
编译器 gcc
概述
Linux系统下的 gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,它是GNU的代表作品之一,gcc是可以在多种硬件平台上编译出可执行文件的超级编译器,其执行效率比一般的编译器要高出20%-30%。编译器能将C、C++语言源程序、汇编语言源程序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个默认名为a.out的可执行文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件,而gcc则通过后缀来区别输入文件的类型。
gcc — c语言编译器
g++ — c++编译器
gcc编译流程
源文件(.c /.h)-> 预处理 -> 编译 -> 汇编 -> 链接(静态库,动态库) -> exe
预编译/预处理 ( 中间文件 —> 后缀 .i )
命令:gcc -E main.c -o main.i
主要处理源文件中,以'#'开头的语句,如 #include、#define 等...
编译 阶段( 中间文件 —> 后缀 .s )
命令:gcc -S main.i -o main.s
预处理完成后,gcc首先检查代码的规范性,以及是否有语法错误等。检查无误后,开始把代码翻译成汇编语言。
汇编 阶段( 中间文件 —> 后缀 .o )
命令:gcc -C main.s -o main.o
在汇编阶段,将输入的汇编文件 *.s,转换成二进制文件 *.o, *.o 已经是二进制文件,即 0 和 1的机器语言,但是,它不是可执行的二进制文件。
链接 阶段( 中间文件 —> 无后缀 exe )
命令:gcc main.o -o main
汇编之后,进入链接。在链接阶段,通过链接各种静态库和动态库,得到可执行文件。
【以上步骤,可简化为命令:gcc main.c -o main】
gcc常用选项(不用死记,用熟即可)
gcc -o 生成指定的输出文件
gcc -v 查询gcc版本信息
gcc -g 生成调试信息,gdb调试器可以利用该信息
gcc -I 指定额外的头文件搜索路径
gcc -L 指定额外的函数库搜索路径
gcc -static 静态链接库,默认都是动态链接库
gcc -w 不生成任何警告信息
gcc -Wall 生成所有警告信息
调试器 gdb
概述
gdb是Linux系统上缺省使用的调试器。gdb也可以被移植到不同的平台上,如ARM系列处理器的调试器
使用方法
在shell终端,直接输入 gdb ,会看到gdb的一些版本信息;然后使用file 命令调试可执行程序。 file 577 (577 为需要调试的可执行程序)
在终端直接输入 gdb 577
常用选项(不用死记,用熟即可)
file file 文件名 加载文件
display display 变量名 显示参数(设置监听变量)
run r run args 运行程序
list l list [开始,结束] 列出文件的代码清单
print p print 变量名 打印变量的内容
break b break [行号或函数名] 设置断点
continue c continue [开始,结束] 继续运行
info i info 变量名 列出信息
next n next 下一行
step S step 进入函数(步入)
quit q 退出
delete delete nu 删除断点 delete nu (nu 表示第几个断点,而不是第几行的断点)
disable disable nu 禁用断点
enable enable nu 恢复禁用的断点
【用起来太别扭了,速度太慢了,可能水平还不够把...】
Makefile
概述
make 是一个命令,用来解析Makefile文件;
Makefile是一个文件,用来告诉 make 命令如何编译整个工程,生成可执行文件。
make执行流程
make命令格式:make [选项] [Makefile 文件]
查找当前目录下的 Makefile 文件;
初始化 Makefile 文件中的变量;
分析 Makefile 中的所有规则;
为所有的文件创建依赖关系;
根据依赖关系,决定哪些目标文件要重新生成;
执行生成命令。
Makefile文件格式
目标: 依赖
命令
执行顺序:
目标是文件,依赖也是文件。
若依赖文件的时间,比目标文件的时间新,说明依赖文件被更新了。则运行规则包含的命令,产生新的目标文件。
如果依赖的是另一条规则的目标,则先跳到另一条规则去执行命令,再返回当前规则。
如果目标不是一个存在的文件,则一定执行。(目标不存在,必须执行)
实例:
main: main.o MyList.o
gcc main.o MyList.o -o main
main.o: main.c
gcc -c main.c -o main.o
MyList.o: MyList.c
gcc -c MyList.c -o MyList.o