1 预备知识
1.1 调试工具
GDB
Unix程序员最常用的调试工具是GDB,这是由Richard Stallman(开源软件运动的领路人)开 发的GNU项目调试器(GNU Project Debugger),该工具在Linux开发中扮演了关键的角色
1.2 调试原则
-
简单工作开始
-
自顶而下
主函数不应该过长,应该大量调用工作函数,如果工作函数过长,可以考虑分解成多个较小的模块,下一次暂停的位置一般在执行函数的下一行
-
调试工具确定段错误位置
通过调用调试器反向追踪(backtrace)功能,获得段错误信息
-
发中断确定无限循环的位置
让程序运行足够的时间以进入循环,用调试器中断命令挂起该程序,用反向追踪获取其调用栈信息
1.3 TUI
1.3.1 处于TUI下的GDB
GDB已经以名为TUI(Terminal User Interface,终端用户界面)的模式提供 了基于文本交互和图形用户交互之间的折中方法。为了以TUI模式运行GDB,可以在调用GDB时在命令行上指定-tui选项,或者处于非TUI模 式时在GDB中使用Ctrl+X+A组合键。如果当前处于TUI模式,后一种命令方式就会使你离开TUI 模式。 在TUI模式中,GDB窗口划分为两个子窗口,一个用于输入GDB命令,而另一个用于查看源 代码。
1.4 主要调试器操作
1.4.1 单步调试源代码
run:运行程序
break:程序在断点处暂停执行
next:执行下一行,不进入函数
step:执行下一行,但会进入函数
continue:恢复执行,直到遇到新断点
tbreak:同样是设置断点,当第一次到达后失效
1.4.2 检查变量
print:输出变量值,给变量赋值
1.4.3 设置监视点应对变量改变
watch:在变量改变时查看程序的状态,变量可以是一个bool类型表达式
1.4.4 上下移动调用栈
函数调用时期,与调用关联的运行时信息存储在称为栈帧(stack frame)的内存区域中
frame:移动调用栈到指定位置
当执行GDB的frame命令时,当前正在执行的函数的帧被编号为0,其父帧(即该函数的调用 者的栈帧)被编号为1,父帧的父帧被编号为2,以此类推
backtrace:显示整个调用栈
1.4.5 联机帮助
help:查看指定指令的帮助文档
1.5 调试会话
1.5.1 GDB方法
在GCC中可以用-g选项让编译器将符号表(即对应于程序的变量和代码行的内存地址 列表)保存在生成的可执行文件中
ctrl+c:halt程序,可确定无限循环的位置
condition 1 num1:只有在num1时才会在断点1处暂停
break 30 if num==1:num等于1时在第三十行暂停
info break:查看断点
clear number:清除第number行的断点
访问不存在内存时发生段错误,手动构造:
int *ptr = NULL;
*ptr = 1;
1.6 启动文件的使用
在重新编译代码时,最好不要退出GDB。这样,你的断点和建立的其他各 种动作都会保留,GDB的启动文件默认名为.gdbinit
2 停下来环顾程序
2.1 暂停机制
- 断点:在程序特定位置暂停
- 监视点:特定内存位置的值发生变化时暂停