悠悠楠杉
网站页面
标题:GDB调试-从入门实践到原理
关键词:GDB调试、Linux调试工具、断点设置、内存分析、调试原理
描述:本文从GDB基础命令入手,通过实战案例解析断点设置与内存分析技巧,最后深入调试原理,帮助开发者掌握Linux环境下的高效调试方法。
正文:
在Linux开发中,GDB(GNU Debugger)是调试C/C++程序的利器。假设我们有一个简单的崩溃程序:
// crash.c
#include
int main() {
int *p = NULL;
printf("%d", *p); // 故意制造段错误
return 0;
}
编译时需添加-g参数保留调试信息:
gcc -g crash.c -o crash启动GDB调试:
gdb ./crash遇到崩溃时,输入bt查看调用栈,frame N切换栈帧,p variable查看变量值。这是最基础的"事后调试"场景。
真正的调试威力在于动态控制。通过以下命令实现:
break main # 在main函数入口设断点
break 5 if p==NULL # 条件断点
watch *p # 内存写入监控
run # 启动程序
next # 单步跳过函数
step # 单步进入函数
continue # 继续运行
x/8wx p # 以16进制显示p指向的8个字
info registers # 查看所有寄存器值
GDB的核心机制值得开发者深究:
ptrace系统调用
GDB通过ptrace(PTRACE_ATTACH,...)附着到目标进程,获得对其寄存器、内存的完全控制权。这也是为什么被调试进程会显示为<defunct>状态。
断点实现原理
- 软件断点:将目标地址指令替换为0xCC(INT3中断指令)
- 硬件断点:利用CPU的调试寄存器DR0-DR3
.debug_info段(DWARF格式),GDB通过该信息建立源代码到机器码的映射关系。可通过readelf -S查看节区信息。
# gdbinit脚本示例
set pagination off
break main
commands 1
print argc
continue
end
run
反向调试
使用record命令记录执行轨迹,通过reverse-step回溯问题发生过程,这对偶现Bug尤为有效。
多线程调试
info threads # 查看所有线程
thread 2 # 切换到线程2