使用GCC与GDB对c语言程序进行调试

使用GCC与GDB对c语言程序进行调试

1. 使用 GCC 编译代码时添加调试信息

在使用 GCC 编译源代码时添加 -g 选项,这会让编译器在生成的可执行文件中包含丰富的调试信息,例如源代码行号、变量名、函数名等,帮助 GDB 建立源代码和机器代码之间的映射关系。

示例代码(test.c
#include <stdio.h>

int add(int a, int b) {
    int result = a + b;
    return result;
}

int main() {
    int num1 = 5;
    int num2 = 10;
    int sum = add(num1, num2);
    printf("The sum is: %d\n", sum);
    return 0;
}
编译命令
gcc -g -o test test.c
❯ gcc -g -o test test.c
❯ ls
test  test.c

这里 -g 用于生成调试信息,-o test 指定生成的可执行文件名为 testtest.c 是源代码文件。

2. 启动 GDB 调试器

编译完成后,使用 gdb 命令启动调试器并加载可执行文件。

gdb test

启动 GDB 后,会显示 GDB 的版本信息和一些提示信息,进入 GDB 的命令行交互界面,提示符为 (gdb)

还可以使用-tui参数进入图形调试界面

gdb -tui test

在这里插入图片描述

3. 在 GDB 中进行调试操作

3.1 设置断点

断点可以让程序在指定位置暂停执行,方便你检查程序状态。

  • 在指定行号设置断点:使用 breakb 命令,后面跟上文件名和行号。例如,在 test.c 文件的第 4 行设置断点:
(gdb) break test.c:4
  • 在函数入口设置断点:直接使用函数名。例如,在 add 函数入口设置断点:
(gdb) break add

在这里插入图片描述

  • 条件断点:可以为断点添加条件,只有当条件满足时,程序才会在该断点处暂停。例如,在 add 函数中,当 a 等于 10 时设置断点:
(gdb) break add if a == 10

在这里插入图片描述

  • 临时断点:使用 tbreak 命令设置的断点只生效一次,程序在该断点处暂停一次后,该断点会自动删除。例如:
(gdb) tbreak main
3.2 查看断点信息

使用 info breakpointsinfo b 命令可以查看当前设置的所有断点信息,包括断点编号、位置、是否启用、命中次数等。

(gdb) info breakpoints

在这里插入图片描述

3.3 启用和禁用断点
  • 禁用断点:使用 disable 命令后面跟上断点编号,可以暂时禁用指定的断点。例如,禁用断点 1:
(gdb) disable 1

在这里插入图片描述

  • 启用断点:使用 enable 命令后面跟上断点编号,可以重新启用被禁用的断点。例如,启用断点 1:
(gdb) enable 1
3.4 删除断点

使用 delete 命令后面跟上断点编号,可以删除指定的断点。例如,删除断点 1:

(gdb) delete 1

在这里插入图片描述
将1,2断点删除后,3,4断点序号不变

3.5 运行程序

使用 runr 命令开始运行程序,程序会在遇到断点时暂停。

(gdb) run

如果程序运行时需要传递命令行参数,可以在 run 命令后面跟上参数。例如:

(gdb) run arg1 arg2

在这里插入图片描述

3.6 单步执行
  • 逐行执行(不进入函数内部):使用 nextn 命令,每次执行一行代码,如果遇到函数调用,会将函数调用作为一行代码执行完。
(gdb) next

在这里插入图片描述

当前断点设置在第10行
在这里插入图片描述
在执行了两步n之后并没有进入add函数进行逐行调试,而是在main函数中逐行调试

  • 逐行执行(进入函数内部):使用 steps 命令,当遇到函数调用时,会进入函数内部逐行执行。
(gdb) step

在这里插入图片描述

现在断点同样设置在第十行

在这里插入图片描述
在执行了两步之后进入了add函数继续执行

  • 跳出当前函数:使用 finish 命令,程序会继续执行直到当前函数返回,并显示函数的返回值。
(gdb) finish

在这里插入图片描述
add函数中执行finish命令跳出了add函数,进入了main函数

3.7 查看变量值

使用 printp 命令查看变量的当前值。

  • 查看普通变量:例如,查看变量 num1 的值:
(gdb) print num1
  • 查看数组元素:假设 arr 是一个数组,查看数组的第一个元素:
(gdb) print arr[0]
  • 查看指针指向的值:假设 ptr 是一个指针,查看指针指向的值:
(gdb) print *ptr
  • 格式化输出:可以使用 print 命令的格式化选项来指定输出格式。例如,以十六进制格式输出变量 num1 的值:
(gdb) print/x num1

在这里插入图片描述

  • 查看当前局部变量的值
(gdb) info locals
3.8 查看源代码
  • 显示当前行附近的源代码:使用 listl 命令可以显示当前执行位置附近的源代码。默认显示 10 行,可以通过设置 listsize 变量来改变显示的行数。
(gdb) list
  • 显示指定行附近的源代码:可以在 list 命令后面跟上行号。例如,显示 test.c 文件第 5 行附近的源代码:
(gdb) list test.c:5
3.9 查看调用栈

使用 backtracebt 命令查看函数调用栈,了解程序的执行流程和函数调用关系。

(gdb) backtrace

在这里插入图片描述

可以使用 frame 命令后面跟上栈帧编号,切换到指定的栈帧,查看该栈帧中的变量和执行位置。例如,切换到栈帧 1:

(gdb) frame 1
3.10 继续执行程序

使用 continuec 命令让程序从当前断点继续执行,直到遇到下一个断点或程序结束。

(gdb) continue
3.11 查看寄存器值

使用 info registers 命令可以查看当前寄存器的值。

(gdb) info registers
3.12 退出 GDB

使用 quitq 命令退出 GDB 调试器。

(gdb) quit

示例调试流程

# 编译代码并添加调试信息
gcc -g -o test test.c

# 启动 GDB 并加载可执行文件
gdb -tui test

# 在 add 函数入口设置断点
(gdb) break add

# 运行程序
(gdb) run

# 进入函数内部单步执行
(gdb) step

# 查看变量值
(gdb) print a
(gdb) print b

# 继续执行到函数返回
(gdb) finish

# 查看调用栈
(gdb) backtrace

# 退出 GDB
(gdb) quit

通过以上详细的步骤和命令,你可以使用 GCC 和 GDB 对 C 程序进行全面而深入的调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值