cgdb的使用
cdgb的介绍
cgdb 是一个基于 GDB 的图形化调试前端,结合了命令行界面的功能和代码查看窗口。它主要是为开发者提供一个更为直观的调试体验,使得在调试程序时既能利用 GDB 强大的调试能力,也能同时查看代码,使得调试过程更加高效和便捷。
主要特点
结合命令行和代码窗口:
cgdb 结合了 GDB 的命令行模式和代码查看窗口,用户可以在一个窗口中同时看到调试命令的输出和源代码。
代码浏览:
你可以在调试过程中直接浏览源代码,跳转到不同的代码行,查看当前行的内容等。这对于调试复杂程序非常有帮助。
支持 GDB 的全部功能:
cgdb 实际上是一个 GDB 的前端,所有 GDB 的功能都可以在 cgdb 中使用,包括设置断点、查看变量、堆栈跟踪、单步执行等。
简洁直观的用户界面:
cgdb 的界面设计简单且直观,适合那些熟悉 GDB 的开发人员。它提供了一个清晰的分屏界面,用户可以轻松地查看源代码和调试命令。
键盘快捷操作:
cgdb 支持丰富的键盘快捷键,使得用户可以快速在源代码和调试命令之间切换,快速定位和执行调试操作。
支持调试多线程程序:
你可以使用 cgdb 调试多线程程序,查看每个线程的堆栈跟踪,并控制每个线程的执行。
源代码高亮:
cgdb 对源代码进行语法高亮显示,帮助开发者更清晰地查看代码结构和调试时的代码内容。
cgdb 的界面结构
cgdb 窗口通常分为两个区域:
上部区域:这是 gdb 命令行的显示区域,用于输入和显示调试命令、断点信息、错误消息等。
下部区域:显示源代码,在调试过程中显示当前执行的代码行,并允许你查看和浏览代码。
安装 cgdb
在大多数 Linux 发行版上,你可以通过包管理工具安装 cgdb:
在 Ubuntu/Debian 上:
sudo apt-get install cgdb
在 Fedora 上:
sudo dnf install cgdb
在 Arch Linux 上:
sudo pacman -S cgdb
cgdb用法
cgdb 是基于 gdb 的调试工具,它的工作依赖于程序包含调试信息。因此,在编译程序时,你需要使用 -g 选项来启用调试信息。常见的编译命令如下:
使用 GCC 编译:
gcc -g -o your_program your_program.c
使用 Clang 编译:
clang -g -o your_program your_program.c
-g 选项将调试信息添加到可执行文件中,允许 cgdb 和 gdb 访问源代码、变量名、函数名等信息。
检查可执行文件是否包含调试信息
你可以使用 file 命令检查编译后的可执行文件是否包含调试信息。命令如下:
file your_program
输出示例:
your_program: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
如果输出中没有提到 “not stripped”,说明可执行文件中没有包含调试信息。在这种情况下,你需要重新编译程序并确保使用了 -g 参数。
启动 cgdb
在确认程序已正确编译并包含调试信息后,你就可以启动 cgdb 来调试你的程序了。使用以下命令启动 cgdb:
cgdb ./your_program
配置 cgdb 以便更好地调试
启动 cgdb 后,默认会打开命令行窗口和源代码窗口。你可以通过以下配置来提升使用体验:
启动调试后自动加载文件
你可以创建一个 .cgdb 配置文件,在其中添加你常用的设置。例如,自动加载符号表、设置断点、加载调试信息等。
例如,在 ~/.cgdb 文件中添加以下内容:
set startup-with-shell off
file ./your_program
这样每次启动 cgdb 时,它会自动加载指定的程序文件。
cgdb常用命令
在 gdb(GNU Debugger)中,有许多常用的命令帮助我们进行程序调试。以下是一些常见的 gdb 指令及其功能:
以这段代码为假设:
编译:
程序控制命令
- run 或 r
启动程序的执行。可以带上命令行参数:
run arg1 arg2
- start
启动程序并在 main() 函数的第一行停住。这比 run 更为直接,适合调试 main 函数。
- continue 或 c
继续执行程序直到下一个断点或程序结束。
- step 或 s
单步执行进入当前函数。遇到函数调用时,会进入到函数内部。
- next 或 n
单步执行,但如果当前行是函数调用,则会跳过进入函数内部,直接执行完函数。
- finish
执行当前函数直到返回,并停在返回点。
- until
执行程序直到当前位置跳出当前的循环或跳出当前的代码块。
- quit 或 q
退出 gdb 调试会话。
断点命令
- break 或 b
在指定位置设置断点。 可以是函数名、行号、文件名+行号等。例如:
break main:在 main() 函数处设置断点。
break 42:在当前文件的第 42 行设置断点。
break foo.c:15:在 foo.c 文件的第 15 行设置断点。
- info breakpoints 或 i b
显示所有当前设置的断点及其状态。
- delete <breakpoint_number>
删除指定的断点。例如,delete 1 删除编号为 1 的断点。(是编号,不是行号)
- disable <breakpoint_number>
禁用指定的断点,而不删除它。
- enable <breakpoint_number>
启用指定的断点。
- clear
删除当前行的断点。你可以指定文件和行号来删除某个位置的断点。例如,clear foo.c:15。
以下命令读者可以自行尝试
堆栈命令
- backtrace 或 bt
打印当前堆栈的调用栈,显示函数调用的顺序。
- frame <frame_number>
切换到指定的堆栈帧。例如,frame 2 切换到调用栈中的第二个函数调用。
- up
向上移动一个堆栈帧,查看调用该函数的地方。
- down
向下移动一个堆栈帧,查看当前函数的调用上下文。
变量和内存命令
- print 或 p
打印变量的当前值。例如:
print x
- set < variable> = < value>
修改变量的值。例如,set x = 10 将变量 x 的值修改为 10。
- info locals
显示当前函数的所有局部变量及其值。
- info args
显示当前函数的所有参数及其值。
- x/< count> < address>
以指定格式查看内存中的内容。count 是查看多少个单元,address 是起始内存地址。例如:
x/4xb $esp
上述命令以十六进制格式查看 esp 寄存器指向的内存。
程序信息命令
- info registers
显示所有处理器寄存器的当前值。
- info threads
显示当前程序中的所有线程。
- thread <thread_id>
切换到指定的线程进行调试。
- list 或 l
显示当前代码上下文。默认显示当前位置前后 10 行代码。你可以指定显示的行数:
list 20
- disassemble 或 disas
显示当前函数或指定地址的汇编代码。例如:
disassemble
disassemble main
条件断点
- break if
设置条件断点。只有当条件满足时,程序才会在该位置停住。例如:
break 42 if x > 10
只有当 x > 10 时,程序才会在第 42 行停住。
调试脚本
- source
运行指定的调试脚本文件,通常是包含一系列 gdb 命令的文本文件。
其他有用命令
- catch
捕获某个特定的事件,比如程序崩溃、异常等。常见事件包括 throw、catch、exec、fork 等。例如:
catch throw
- watch < variable>
设置一个观察点,监视变量的变化,当该变量的值发生变化时,程序会停住。
- record
启用历史记录功能,记录程序的执行轨迹,并可以回放历史步骤。