GDB - 调试程序
入门:启动和停止
gcc -g myprogram.c
使用调试选项 (-g) 编译 myprogram.c。您仍会得到一个 a.out,但它包含调试信息,可让您在 GDB 中使用变量和函数名称,而不是原始内存位置(不好玩)。
gdb a.out
使用文件 a.out 打开 GDB,但不运行该程序。您将看到一个提示符 (gdb) - 所有示例均来自此提示符。
r
r arg1 arg2
r < file1
三种方式运行之前加载的"a.out"。您可以直接运行它 (r)、传递参数 (r arg1 arg2) 或输入文件。您通常会在运行之前设置断点。
help
h breakpoints
列出帮助主题 (help) 或获取特定主题的帮助 (h 断点)。GDB 有详尽的文档。
q - Quit GDB
单步执行代码
单步执行可让您跟踪程序的路径,并集中精力查找崩溃或返回无效输入的代码。
l
l 50
l myfunction
列出当前行 (l)、特定行 (l 50) 或某个函数 (l myfunction) 的 10 行源代码。
next
运行程序直到下一行,然后暂停。如果当前行是一个函数,它将执行整个函数,然后暂停。next 适合快速浏览代码。
step
运行下一条指令,而不是行。如果当前指令正在设置变量,则与 next 相同。如果它是一个函数,它将跳转到该函数,执行第一个语句,然后暂停。step 适合深入了解代码的细节。
finish
完成当前函数的执行,然后暂停(也称为 step out)。如果您不小心进入了某个函数,则很有用。
断点或观察点
断点在调试中起着重要作用。当程序到达某个点时,它们会暂停(中断)程序。您可以检查和更改变量并恢复执行。当发生某些输入故障或需要测试输入时,这很有用。
break 45
break myfunction
- 在第 45 行或 myfunction 处设置断点。程序到达断点时会暂停。
watch x == 3
设置一个监视点,当条件发生变化时(当 x == 3 发生变化时)暂停程序。监视点非常适合某些输入(myPtr != NULL),而无需在每次函数调用时中断。
continue
被断点/监视点暂停后恢复执行。程序将继续运行,直到到达下一个断点/观察点。
delete N
- 删除断点 N(断点在创建时已编号)。
设置变量
在运行时查看和更改变量是调试的关键部分。尝试向函数提供无效输入或运行其他测试用例以找出问题的根本原因。通常,您会在程序暂停时查看/设置变量。
print x
打印变量 x 的当前值。能够使用原始变量名是需要 (-g) 标志的原因;定期编译的程序会删除此信息。
set x = 3
set x = y
- 将 x 设置为设定值 (3) 或另一个变量 (y)
call myfunction()
call myotherfunction(x)
call strlen(mystring)
调用用户定义或系统函数。这非常有用,但要小心调用有缺陷的函数。
display x
持续显示变量 x 的值,该值在每个步骤或暂停后显示。如果您不断检查某个值,则很有用。
undisplay x
- 删除由 display 命令显示的变量的常量显示。
回溯和更改框架
堆栈是当前函数调用的列表 - 它显示您在程序中的位置。框架存储单个函数调用的详细信息,例如参数。
bt
回溯或打印当前函数堆栈以显示您在当前程序中的位置。如果 main 调用函数 a(),该函数调用 b(),该函数调用 c(),则回溯是
c <= current location b a main
up
down
在函数堆栈中向上或向下移动到下一帧。如果您在 c 中,则可以移动到 b 或 a 来检查局部变量。
return
- 从当前函数返回。
处理信号
信号是在某些事件(例如计时器或错误)后抛出的消息。GDB 遇到信号时可能会暂停;您可能希望忽略它们。
handle [signalname] [action]
handle SIGUSR1 nostop
handle SIGUSR1 noprint
handle SIGUSR1 ignore
指示 GDB 在出现某个信号 (SIGUSR1) 时将其忽略。忽略有多种级别。