文章目录
- 前言
- 一、基础
- 二、例子
- 三、用gdb调试多线程程序
前言
GDB(GNU Debugger)是一个强大的调试工具,用于调试C、C++等编程语言的程序。本文将介绍一些常用的GDB指令,以及通过例子演示如何使用这些指令进行程序调试。
一、基础
-
启动程序调试:
使用命令gdb <executable>
启动GDB,并加载可执行文件进行调试。 -
设置断点:
- 使用命令
break <location>
或b <location>
设置断点。<location>
可以是函数名、行号或文件名:行号的组合。例如,break main
在main
函数处设置断点。 - 使用命令
info breakpoints
或i b
查看已设置的断点信息。 - 使用命令
delete <breakpoint_number>
删除指定编号的断点。
- 使用命令
-
运行程序:
- 使用命令
run
或r
运行程序,可以在后面跟上命令行参数。 - 使用命令
continue
或c
继续执行程序,直到下一个断点或程序结束。
- 使用命令
-
单步调试:
- 使用命令
next
或n
执行下一行代码,不会进入函数内部。 - 使用命令
step
或s
执行下一行代码,并进入函数内部。
- 使用命令
-
打印变量值:
- 使用命令
print <expression>
或p <expression>
打印表达式的值。例如,print x
打印变量x
的值。 - 使用命令
info locals
显示当前作用域的局部变量。
- 使用命令
-
调试信息:
- 使用命令
backtrace
或bt
显示当前调用栈的信息。 - 使用命令
info registers
或i r
查看寄存器的值。
- 使用命令
-
观察点:
- 使用命令
watch <expression>
设置观察点,当表达式的值发生变化时中断程序执行。
- 使用命令
-
退出GDB:
- 使用命令
quit
或q
退出GDB。
- 使用命令
通过以上常用指令,我们可以对程序进行有效的调试。
二、例子
下面是一个简单的例子,演示如何使用GDB调试程序:
假设我们有以下C程序,保存为 example.c
:
#include <stdio.h>
int main() {
int num1 = 10;
int num2 = 5;
int sum = num1 + num2;
printf("The sum of %d and %d is %d\n", num1, num2, sum);
return 0;
}
我们希望使用GDB调试这个程序,以查找并解决潜在的问题。
-
编译程序时需要添加
-g
参数,以生成可调试的符号表。例如,使用以下命令编译程序:gcc -g example.c -o example
-
启动GDB,并加载可执行文件:
gdb example
-
设置断点:
break main
这将在
main
函数的第一行设置断点。 -
运行程序:
run
程序将运行到第一个断点处停止。
-
单步调试:
使用
next
命令逐行执行代码:next
第一次执行
next
后,程序将执行到第二行int num2 = 5;
处。此时,我们可以使用print
命令查看变量的值:print num1
输出结果为:
$1 = 10
这表示变量
num1
的值为 10。继续执行
next
命令,程序将执行到第三行int sum = num1 + num2;
处。我们可以使用step
命令进入+
操作符对应的函数内部:step
程序将进入
+
函数内部。此时,我们可以使用print
命令查看参数的值:print num1 print num2
输出结果为:
$2 = 10 $3 = 5
这表示变量
num1
和num2
的值分别为 10 和 5。继续执行
next
命令,程序将执行到第四行printf("The sum of %d and %d is %d\n", num1, num2, sum);
处。我们可以使用print
命令查看变量的值:print sum
输出结果为:
$4 = 15
这表示变量
sum
的值为 15。 -
继续执行程序:
使用
continue
命令继续执行程序:continue
程序将执行完毕并退出。
-
退出GDB:
使用
quit
命令退出GDB:quit
通过以上步骤,我们成功使用GDB调试了这个简单的C程序。在实际的开发中,我们可以使用更多的GDB指令和技巧,以更高效地进行程序调试。
三、用gdb调试多线程程序
对这些GDB命令的整理和示例:
-
info threads
:显示当前可调试的所有线程。每个线程都有一个唯一的ID,被调试的线程前面会有一个"*"标记。示例输出:
(gdb) info threads * 1 Thread 0x7ffff7fcf700 (LWP 1234) "program" 0x0000555555555163 in worker_thread () 2 Thread 0x7ffff77ce700 (LWP 1235) "program" 0x0000555555555163 in worker_thread ()
-
thread ID
:切换到指定ID的线程进行调试。示例:
(gdb) thread 2 [Switching to thread 2 (Thread 0x7ffff77ce700 (LWP 1235))] #0 0x0000555555555163 in worker_thread ()
-
set scheduler-locking [off|on|step]
:控制调试时其他线程的执行方式。off
:不锁定任何线程,即所有线程都可以继续执行(默认值)。on
:只有当前被调试的线程会继续执行。step
:在单步执行时,只有当前线程会执行。
示例:
(gdb) set scheduler-locking on Scheduler locking is on.
这些命令可以帮助您在调试多线程程序时进行线程的切换和控制,以及查看当前可调试的线程信息。通过合理使用这些命令,您可以更好地理解和调试多线程程序的执行过程。