GCC 与 GDB 的学习

gcc 是 GUN Compiler Collection的缩写,可以支持多种语言编译,比如 C, C++, Java, pascal 等

gcc的编译过程

  • 预处理(pre-processing)E:插入头文件,替换宏

  • 编译(Compiling)S:编译成汇编

  • 汇编(Assembling) c:编译成目标文件

  • 链接 (Linking):链接到库中,变成可执行文件

gcc -E hello.c -o hello.i

gcc -S hello.i –o hello.s

gcc –c hello.s –o hello.o

gcc hello.s –o hello 链接,生成可执行文件

./hello 运行

也可以一次性完成:

gcc hello.c –o hello

但一般情况下生成.o文件比较好,可以重定位文件,让别人使用

gcc常用选项

选项名 作用
o 生成目标
c 取消链接步骤,编译源码并最后生成目标文件
E 只运行C预编译器(头文件,宏等展开)
S 生成汇编语言文件后停止编译(.s文件)
Wall 打开编译告警(所有)
g 嵌入调试信息,方便gdb调试
llib 链接 lib 库 (这里是小写 L ) 相当于 C++ #pragma comment(lib, “xxx.lib”)
Idir 增加 include 目录 (这里是大写 i ) 头文件路径
LDir 增加 lib 目录 (编译静态库和动态库)

gdb调试实例
下面以一个有错误的例子程序来介绍gdb的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*bugging.c*/
#include <stdio.h>
#include <stdlib.h>

static char buff [256];
static char* string;
int main ()
{
printf ("Please input a string: ");
gets (string);
printf ("\nYour string is: %s\n", string);
}
//这个程序是接受用户的输入,然后将用户的输入打印出来。该程序使用了一个未经过初始化的字符串地址 string,因此,编译并运行之后,将出现 "Segment Fault"错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ gcc -o bugging -g  bugging.c
$ ./bugging

# Please input a string: asdf
# Segmentation fault (core dumped)
# 为了查找该程序中出现的问题,我们利用 gdb,并按如下的步骤进行:

# [1] 运行 “gdb bugging” ,加载 bugging 可执行文件;
$gdb bugging

#[2] 执行装入的 bugging 命令;
(gdb) run

#[3] 使用 where 命令查看程序出错的地方;
(gdb) where

#[4] 利用 list 命令查看调用 gets 函数附近的代码;
(gdb) list

#[5] 在 gdb 中,我们在第 11 行处设置断点,看看是否是在第11行出错;
(gdb) break 11

#[6] 程序重新运行到第 11 行处停止,这时程序正常,然后执行单步命令next;
(gdb) next

#[7] 程序确实出错,能够导致 gets 函数出错的因素就是变量 string。重新执行测试程,用 print 命令查看 string 的值;
(gdb) run
(gdb) print string
(gdb) $1=0x0

#[8] 问题在于string指向的是一个无效指针,修改程序,在10行和11行之间增加一条语句 “string=buff; ”,重新编译程序,然后继续运行,将看到正确的程序运行结果。

用gdb查看源代码可以用list命令,但是这个不够灵活。可以使用”layout src”命令,或者按Ctrl-X再按A,就会出现一个窗口可以查看源代码。也可以用使用-tui参数,这样进入gdb里面后就能直接打开代码查看窗口。其他代码窗口相关命令:

info win 显示窗口的大小
layout next 切换到下一个布局模式
layout prev 切换到上一个布局模式
layout src 只显示源代码
layout asm 只显示汇编代码
layout split 显示源代码和汇编代码
layout regs 增加寄存器内容显示
focus cmd/src/asm/regs/next/prev 切换当前窗口
refresh 刷新所有窗口
tui reg next 显示下一组寄存器
tui reg system 显示系统寄存器
update 更新源代码窗口和当前执行点
winheight name +/- line 调整name窗口的高度
tabset nchar 设置tab为nchar个字符



GCC 与 GDB 的学习
https://chaggle.github.io/2021/10/06/middleware/gcc/
作者
chaggle
发布于
2021年10月6日
许可协议