您现在的位置是:网站首页>技术百科技术百科
Linux 下 GDB 调试方法
小大寒2024-01-01[技术百科]博学多闻
Linux 下 GDB 调试方法 GDB是GNU项目的调试器,可让你在程序执行时查看其内部运行情况,或在程序崩溃时了解其当时状态。GDB主要功能包括启动程序、设置条件停止程序、检查程序停止时的状态、修改程序以实验性修复错误。它支持本地、远程和模拟环境,并可在大多数UNIX、Windows和macOS系统上运行。
Linux 下 GDB 调试方法
GDB(GNU 调试器)是一个强大的调试工具,它可以帮助开发者在程序运行时分析问题。以下内容将结合 C 语言代码,详细讲解如何在 Linux 下使用 GDB 进行调试。
1. 安装 GDB
如果系统没有安装 GDB,可以使用以下命令进行安装:
sudo apt-get install gdb
2. 使用 GDB 调试 C 语言代码
首先,我们编写一个简单的 C 语言代码,使用 GDB 来调试。
示例代码:
#include <stdio.h>
void greet(char *name) {
printf("Hello, %s!\n", name);
}
int main() {
char *name = "World";
greet(name);
return 0;
}
以上代码定义了一个 greet
函数,用于打印欢迎信息。
3. 编译代码
为了使用 GDB 进行调试,我们需要在编译时加上调试符号。使用 -g
参数来生成调试信息:
gcc -g -o greet greet.c
该命令将生成一个名为 greet
的可执行文件,并包含调试信息。
4. 启动 GDB
要启动 GDB 调试,我们可以使用以下命令:
gdb ./greet
进入 GDB 后,您将看到类似于下面的提示:
(gdb)
5. 设置断点
在 GDB 中,我们可以设置断点来暂停程序的执行并进行检查。假设我们想在 greet
函数的开始处设置一个断点,可以使用如下命令:
(gdb) break greet
此命令会在 greet
函数的第一行设置一个断点。
6. 运行程序
设置好断点后,使用 run
命令来启动程序:
(gdb) run
程序会在断点处暂停,这时我们可以检查程序的状态。
7. 查看变量值
当程序暂停时,我们可以使用 print
命令查看变量的值。例如,查看 name
变量的值:
(gdb) print name
这将显示 name
变量的当前值:
$1 = 0x5555555562c0 "World"
8. 单步执行
要逐行执行代码,可以使用 next
命令:
(gdb) next
这会执行当前行,并在下一行暂停。您还可以使用 step
命令进入函数调用:
(gdb) step
9. 查看调用栈
当程序在断点处暂停时,可以使用 backtrace
命令查看调用栈:
(gdb) backtrace
这将显示函数调用的层次结构:
#0 greet (name=0x5555555562c0 "World") at greet.c:5
#1 0x000055555555517d in main () at greet.c:10
10. 继续执行程序
如果想继续执行程序直到下一个断点,可以使用 continue
命令:
(gdb) continue
11. 退出 GDB
调试完成后,使用 quit
命令退出 GDB:
(gdb) quit
GDB 是一个强大的调试工具,支持多种调试功能,例如设置断点、查看变量、单步执行、查看调用栈等。通过结合实际的 C 语言代码,您可以在 Linux 环境中有效地调试您的程序。
上面是给GDB零基础的人看的,下面的才是正餐
一、多线程调试
多线程调试通常是最常见的问题之一。其实,关键的命令如下:
- info thread: 显示当前进程中的线程。
- thread <ID>: 切换到指定线程ID进行调试。
- break file.c:100 thread all: 在file.c文件的第100行,为所有经过该行的线程设置断点。
- set scheduler-locking off|on|step: 这也是最常被提问的命令。当你在使用step或continue命令调试当前线程时,其他线程仍会继续执行。通过这个命令,你可以控制是否锁定其他线程。
- off: 不锁定任何线程,所有线程都执行(默认值)。
- on: 只有当前调试的线程会继续执行。
- step: 单步调试时,除非是next跳过一个函数,否则只有当前线程会执行。
二、调试宏
调试宏是一个常见的问题。在GDB中,我们无法直接打印宏定义,因为宏在编译前就已经展开了。然而,通过GCC的帮助,我们依然能够调试宏。
在GCC编译时加上-ggdb3选项,你就可以调试宏了。
此外,你还可以使用以下命令来调试宏:
- info macro: 查看宏在哪些文件中被引用及其定义。
- macro: 查看宏展开后的内容。
三、源文件
关于源文件的问题也非常常见。很多人经常会遇到找不到源文件的情况。此时,你可以检查以下几点:
- 编译时是否加上了-g选项以包含调试信息。
- 路径设置是否正确。可以使用GDB的directory命令设置源文件目录。
下面是一个调试/bin/ls的示例(在Ubuntu系统上):
$ apt-get source coreutils $ sudo apt-get install coreutils-dbgsym $ gdb /bin/ls GNU gdb (GDB) 7.1-ubuntu (gdb) list main 1192 ls.c: No such file or directory. in ls.c (gdb) directory ~/src/coreutils-7.4/src/ Source directories searched: /home/tom/src/coreutils-7.4:$cdir:$cwd (gdb) list main 1192 } 1193 } 1194 1195 int 1196 main (int argc, char **argv) 1197 { 1198 int i; 1199 struct pending *thispend; 1200 int n_files; 1201
四、条件断点
条件断点的语法为:break [where] if [condition],这种断点非常有用,特别是在循环或递归中,或者当你需要监控某个变量时。请注意,这个条件检查是在GDB中的,每次经过断点时,GDB都会检查条件是否满足。
五、命令行参数
有时,我们需要为调试的程序传递命令行参数,很多人可能不知道如何设置。其实,有两种方法:
- 在gdb命令行中使用 --args 参数。
- 使用GDB中的 set args 命令设置。
六、GDB中的变量
在调试过程中,除了查看运行时变量外,我们还可以直接修改程序中的变量,这样有助于模拟一些特殊的情境,尤其是当遇到错误或需要跳过特定分支时。使用set命令,你可以修改程序中的变量。
另外,GDB也有类似于shell的变量,变量名前缀为$。比如,你可以通过下面的方式打印数组中的元素:
(gdb) set $i = 0 (gdb) p a[$i++] ... # 然后继续按回车即可查看数组元素
这表明程序变量和GDB变量可以互相交互。
七、x命令
你可能习惯使用p命令来查看变量值。但是,当你不知道变量名时,可能会陷入困境,因为p命令需要提供变量名。此时,你可以使用x命令查看内存内容。在GDB中,输入“help x”可以查看更多帮助。
- x/x: 以十六进制格式显示。
- x/d: 以十进制格式显示。
- x/c: 以字符形式显示。
- x/i: 反汇编,通常你可以使用
x/10i $ip-20
来查看当前的汇编($ip是指令指针寄存器)。 - x/s: 以字符串形式显示。
八、command命令
很多朋友问我如何实现自动化调试。这里我向大家介绍GDB的command命令,简单来说,它可以把一组GDB命令打包执行,有点像字处理软件中的“宏”功能。以下是一个示例:
(gdb) break func Breakpoint 1 at 0x3475678: file test.c, line 12. (gdb) command 1 Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >print arg1 >print arg2 >print arg3 >end (gdb)
当断点命中时,GDB会自动执行command中的三个命令,打印出func函数的三个参数值。
上面的GDB技巧应该足够你在绝大多数情况下使用了,如果你觉得不够用,请移步GDB官网继续深入。GDB官网
阅读完毕,很棒哦!