1.编译器主要组件
- 分析器:将源语言程序代码转换为汇编语言
- 汇编器:将汇编代码转换为CPU可执行的字节码
- 链接器:将汇编器生成的单独目标文件组合成可执行的应用程序
- 标准C库:在应用程序中用到C库中的函数,这个库就会通过链接器和源代码连接来生成最终可执行程序
2.GCC基本用法和选项
GCC基本用法是gcc [options] [filename]
- -c,只编译,不连接成可执行文件,编译器只是由输入的.c等源代码生成以.o为后缀的目标文件,通常用来编译不包含主程序的子程序文件
- -o output_filename,确定输出文件名称为output_filename,同时这个名称不能与源文件同名。如果不给输出文件名,则会默认生成a.out可执行文件
- -g,产生符号调试工具(GUN的gdb)所必要的符号资讯,想要调试源代码,必须加入该选项
- -O,对程序进行优化编译,对应编译,连接速度变慢
- -O2,比-O更好地优化编译
- -I dirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数
- -L dirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数
3.GCC常见错误类型及对策
- C语法错误(syntex error)
- 头文件错误(Can not find include file xx.h)
- 档案库错误(ld: -lm: No such file or directory),即找不到库函数
- 未定义符号(Undefined symbol)
4.GCC编译过程
#include
#include
#define N 10
#define _DEBUG_
int main(int argc, const char *argv[])
{
int m = 10, n;
m += N;
n = sqrt(m);
#ifdef _DEBUG_
printf("debug:m=%d n=%d\n", m, n);
#else
printf("nodebug:m=%d n=%d\n", m, n);
#endif
return 0;
}
注意:在此处用到math.h,在编译时候需要链接-lm(通过man sqrt
查看sqrt函数手册)
hanqi@hanqi-PC:~/gccdemo$ gcc -o demo1 demo1.c -Wall -lm
hanqi@hanqi-PC:~/gccdemo$ ./demo1
debug:m=20 n=4
- 预处理,.c文件变.i文件
a.把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。
b.预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。
c.预处理器将源程序文件中出现的对宏的引用展开成相应的宏定义,即本文所说的#define的功能,由预处理器来完成。
hanqi@hanqi-PC:~/gccdemo$ gcc -E demo1.c -o demo1.i
- 编译,.i文件变.s文件
a.将预处理之后的代码转换为汇编代码
hanqi@hanqi-PC:~/gccdemo$ gcc -S demo1.i -o demo1.s
- 汇编,.s文件变.o文件
a.检查语法错误,生成汇编文件
b.将汇编代码转换为机器码
hanqi@hanqi-PC:~/gccdemo$ gcc -c demo1.s -o demo1.o
- 链接,.o文件变.exe文件
a.将多个目标文件和其所对应的库链接为最终可执行文件
hanqi@hanqi-PC:~/gccdemo$ gcc demo1.o -o demo1 -lm
5.GDB调试流程
- 使用gcc对.c进行编译,加上
-g
hanqi@hanqi-PC:~/gccdemo$ gcc -g demo1.c -o demo1 -lm
hanqi@hanqi-PC:~/gccdemo$ gdb demo1.out
- l,查看源码,多次l查看下一页源码,l num,跳转到第num页
(gdb) l
1 #include
2 #include
3
4 #define N 10
5 #define _DEBUG_
6
7 int main(int argc, const char *argv[])
8 {
9 int m = 10, n;
10 m += N;
(gdb) l
11 n = sqrt(m);
12
13 #ifdef _DEBUG_
14 printf("debug:m=%d n=%d\n", m, n);
15 #else
16 printf("nodebug:m=%d n=%d\n", m, n);
17 #endif
18 return 0;
19 }
(gdb) l
Line number 20 out of range; demo1.c has 19 lines.
(gdb) l 1
1 #include
2 #include
3
4 #define N 10
5 #define _DEBUG_
6
7 int main(int argc, const char *argv[])
8 {
9 int m = 10, n;
10 m += N;
(gdb)
- b num,在第num行设置断点
(gdb) b 9
Breakpoint 1 at 0x72f: file demo1.c, line 9.
(gdb) b 11
Breakpoint 2 at 0x73a: file demo1.c, line 11.
(gdb)
- info b,查看断点信息
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000072f in main at demo1.c:9
2 breakpoint keep y 0x000000000000073a in main at demo1.c:11
(gdb)
- del num,删除第num个断点
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000072f in main at demo1.c:9
2 breakpoint keep y 0x000000000000073a in main at demo1.c:11
(gdb) del 1
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000000073a in main at demo1.c:11
(gdb)
- q,退出调试
- r, 运行代码
(gdb) r
Starting program: /home/hanqi/gccdemo/demo1
Breakpoint 2, main (argc=1, argv=0x7fffffffcde8) at demo1.c:11
11 n = sqrt(m);
(gdb)
- p m,查看变量m的值
(gdb) p m
$1 = 20
(gdb) p n
$2 = 0
(gdb)
- n,单步运行跳过函数;s,单步运行进入函数
(gdb) n
14 printf("debug:m=%d n=%d\n", m, n);
(gdb)
- c,恢复程序运行
(gdb) c
Continuing.
debug:m=20 n=4
[Inferior 1 (process 34720) exited normally]
(gdb)
- set args 参数:指定运行时的参数
- show args:查看设置好的参数
部分参考链接:https://blog.csdn.net/niyaozuozuihao/article/details/91802994