GDB(GNU Debugger)是一个强大的命令行调试工具,用于调试C、C++等编程语言的程序。以下是一些常用的GDB调试命令:
一、启动 GDB:打开终端并输入以下命令来启动GDB,并将可执行文件作为参数
gdb ld-new
二、运行程序:在GDB中,使用 run
命令来启动被调试的程序。
(1)新建一个hello.c文件
#include <stdio.h>
int main() {
int num = 42;
char str[] = "Hello, World!";
printf("This is an integer: %d\n", num);
printf("This is a string: %s\n", str);
return 0;
}
(2) 编译成.o文件
gcc -c hello.c
(3) run使用ld-new可执行文件,运行.o文件
在main处打断点
b main
run /home/newuser/projects/hello.o
三、 查看栈帧信息:使用 bt
命令来查看当前的调用栈信息。
bt
四、单步执行:使用 step
命令来逐行执行程序,包括进入函数内部。
step
s
命令(step
):
s
是 "step" 的缩写。- 当你输入
s
命令时,GDB将逐行执行程序,包括进入调用的函数内部。 - 如果当前行上的函数是一个函数调用,
s
将进入该函数,允许你逐行调试函数内部的代码。 s
通常用于深入了解程序的内部工作,包括函数内部的执行路径。
五、逐语句执行:使用 next
命令来逐语句执行程序,不会进入函数内部。
next
n
命令(next
):
n
是 "next" 的缩写。- 当你输入
n
命令时,GDB将执行当前行上的函数并直接跳到下一行。 - 如果当前行上的函数是一个调用其他函数的函数,
n
将执行整个函数调用,然后在调用返回后停在下一行。 n
不会进入被调用的函数内部,它只会执行当前函数的上下文,然后移到下一行。
六、列出断点
info breakpoints
七、继续执行:使用 continue
命令继续执行程序,直到遇到下一个断点或程序结束。
continue
八、查看变量值:使用 print
命令来查看变量的值。
print variable_name
九、 设置条件断点:使用 break
命令的条件选项来设置条件断点,只有当条件为真时才会触发断点。
break if condition
1. 监视变量:watch
命令用于监视变量的值,当变量的值发生变化时,GDB会中断程序执行。
watch variable_name
2. 设置显示格式:使用 set
命令设置变量显示的格式,如显示十六进制、二进制等。
set variable format
十、启用源代码布局、启用汇编窗口、启用寄存器窗口
10.1 启动源代码布局
在GDB中,layout src
命令用于在调试会话中启用源代码布局。这个命令会将源代码窗口添加到GDB界面,使你可以在调试时直接查看源代码。请注意,使用这个命令需要支持TUI(Text User Interface)的终端。
(gdb) layout src
10.2 启动汇编布局
(gdb) layout asm
10.3 启动寄存器窗口
(gdb) layout reg
十一、开启core dump采集程序崩溃信息
core文件是程序崩溃或异常终止时生成的一种核心转储文件,其中包含程序在崩溃时的内存和寄存器状态。分析core文件有助于诊断程序崩溃的原因。
11.1 查看当前资源限制:
ulimit -a
11.2 设置资源限制:
这个例子将核心转储文件的大小限制设置为无限制。其他资源限制也可以通过类似的方式进行设置。
ulimit -c unlimited
11.3 常见的 ulimit
参数包括:
- -c: 设置或显示核心转储文件的大小限制。
- -n: 设置或显示文件描述符的数量限制。
- -u: 设置或显示用户进程数的限制。
11.4 启动 GDB 并加载程序核心转储文件
gdb ./your_program core
十二、多线程调试
set scheduler-locking on
是 GDB(GNU Debugger)中的一个命令,用于启用或禁用调度器锁定。调度器锁定是 GDB 的一个特性,用于在调试多线程程序时控制线程调度。
当启用调度器锁定时,GDB 会尽量保持目标程序中的线程处于挂起状态,以防止它们被操作系统调度器在调试过程中无意中运行。这有助于提高调试的可控性。
具体用法如下:
set scheduler-locking on
这个命令告诉 GDB 启用调度器锁定。在这种模式下,GDB 将尝试确保目标程序的线程在执行 GDB 命令期间保持挂起状态。
如果你想禁用调度器锁定,可以使用以下命令:
set scheduler-locking off
请注意,调度器锁定并非在所有情况下都是必需的,而且在某些情况下可能会导致调试器表现不稳定。在一般情况下,你可能无需手动设置这个选项,因为 GDB 通常会自动选择适当的模式。
十三、查看内存错误工具
一、使用Valgrind
Valgrind是一个内存检测工具,它还可以用于分析core文件。你可以使用valgrind
命令来运行你的程序,在编译程序时,确保添加调试信息。这有助于Valgrind提供更详细的输出。
g++ -g -o your_program your_program.cpp
运行程序: 使用Valgrind运行你的程序。例如:
valgrind ./your_program
Valgrind将执行你的程序,并在检测到内存错误时输出相应的信息。
Valgrind支持的一些主要工具:
Memcheck:
- 用途: 用于检测内存错误,例如内存泄漏、越界访问、使用未初始化的内存等。
- 使用命令:
valgrind ./your_program
Cachegrind:
- 用途: 用于缓存分析,可以帮助你理解程序在CPU缓存上的性能表现。
- 使用命令:
valgrind --tool=cachegrind ./your_program
Callgrind:
- 用途: 用于函数调用跟踪,提供详细的函数调用图、调用关系和执行次数。
- 使用命令:
valgrind --tool=callgrind ./your_program
Helgrind:
- 用途: 用于检测多线程程序中的并发错误,例如数据竞争。
- 使用命令:
valgrind --tool=helgrind ./your_program
Massif:
- 用途: 用于堆内存分析,可以帮助你了解程序的堆内存使用情况,包括内存分配和释放。
- 使用命令:
valgrind --tool=massif ./your_program
DHAT(Dynamic Heap Analysis Tool):
- 用途: 用于动态堆分析,可帮助你了解程序中的动态内存分配和释放。
- 使用命令:
valgrind --tool=dhat ./your_program
SGCheck:
- 用途: 用于检测内存中的单词错误(例如,使用未初始化的内存)。
- 使用命令:
valgrind --tool=exp-sgcheck ./your_program
BBV(Basic Block Vector):
- 用途: 用于计算基本块的矢量信息,有助于理解程序中的基本块执行情况。
- 使用命令:
valgrind --tool=exp-bbv ./your_program
二、ASAN
AddressSanitizer(ASAN)是一种内存错误检测工具,它能够检测程序中的内存越界、内存泄漏等问题。要将程序使用ASAN进行编译,你需要进行以下步骤:
使用ASAN编译程序: 编译程序时,需要使用-fsanitize=address
选项来启用ASAN。同时,建议添加-g
选项以包含调试信息,以便在检测到问题时更容易进行调试:
g++ -fsanitize=address -g -o your_program your_program.cpp
运行程序:
编译后的程序将包含ASAN运行时库。当程序运行时,ASAN将检测内存错误并在控制台输出相应的信息。例如:
./your_program