背景: 最近在重新学习操作系统,顺带重学一下C语言,GDB是C语言进行调试的工具,也就重新学一下GDB,本文没有什么创新只是记录所学内容,供以后翻阅和查询。
一、首先需要安装一系列软件
apt-get install build-essential # build-essential packages, include binary utilities, gcc, make, and so on
apt-get install man # on-line reference manual
apt-get install gcc-doc # on-line reference manual for gcc
apt-get install gdb # GNU debugger
apt-get install git # revision control system
apt-get install libreadline-dev # a library used later
apt-get install libsdl2-dev # a library used later
apt-get install llvm llvm-dev # llvm project, which contains libraries used later
二、案例程序
gcc -Wall -Werror? -g test.c -o test.out
-g 代表将生成带有调试信息的可执行文件,-o是输出
#include<stdio.h>
int actual_calc(int a, int b){
int c;
c=a/b;
return 0;
}
int calc(){
int a;
int b;
a=13;
b=0;
actual_calc(a, b);
return 0;
}
void output(){
printf("this is a output\n");
}
int main(){
output();
calc();
return 0;
}
三、使用gdb
1. 加载程序
有两种方式:
$ gdb test.out
或
$ gdb
(gdb) file test.out?
2.运行程序
(gdb) run 或 r
3.设置断点
断点可以设置某一行,也可以设置某个函数
(gdb) break file1.c:6? ? ? ? ? ?// 将设置 file1.c文件的第6行
(gdb) break my_function? ? // 将设置my_function作为断点
(gdb) break file1.c:6 if i >= ARRAYSIZE? ? // 有条件的设置断点
break也可以简写为 b
(gdb) disable b? ? ? ? ? ? ? ? ? ?// 关闭全部的断点
(gdb) enable b? ? ? ? ? ? ? ? ? ? // 打开全部的断点?
4.查看所有断点
(gdb) info break
(gdb) info b
5. 删除断点
(gdb) delete Num? ? ? ? ? ? ? ?// Num为上一步查看断点的标号
(gdb) clear? 函数名称? ?? ? ? //? 删除 函数名称 的断点
(gdb) clear 行号? ? ? ? ? ? ? ? ?//? 删除 行号 处的断点
6.设置观察点
(gdb) watch my_var? ? ? ? ? ?// 观察变量my_var是否变化,如有变化则停止程序并打印旧值和新值
7.继续运行
(gdb) continue 或 c? ? ? ? ? ? ?// 当遇到断点停下来的时候,使用continue或c使程序继续运行
8.打印变量
(gdb) print my_var? ? ? ? ? ? ? ?// 打印变量my_var的值
(gdb) print/x my_var? ? ? ? ? ? ?// 打印变量my_var的十六进制的值
(gdb) print p->key? ? ? ? ? ? ? ? ?// 打印结构体指针的变量值
(gdb) print (*p).key? ? ? ? ? ? ? ? //? 同上
(gdb) print p->name? ? ? ? ? ? ? // 打印结构体指针的变量值
(gdb) print (*p).name? ? ? ? ? ? // 同上
(gdb) print p? ? ? ? ? ? ? ? ? ? ? ? ? // 打印指针的地址
(gdb) print *p? ? ? ? ? ? ? ? ? ? ? ? // 打印指针所指向的值,或结构体的内容
print 也可以简写为 p
9. backtrace
(gdb) backtrace? ? ? ? ? ? ? ? ? ? // 回溯,打印栈
(gdb) where
(gdb) finish
10. 执行一步
(gdb) step?
如果多次执行一步,可以使用 回车 替代输入,这样减少了很多输入的麻烦。
step 可简写为s? 它会进入到各个函数中
next 可简写为n? 它不会进入到各个函数中,而是当函数作为一条指令。
11. 显示代码
(gdb) list? 或 l? ? ? ? ? ? ? ? ?// 默认显示10行,回车显示其余的代码
(gdb) list 20? ? ? ? ? ? ? ? ? ?// 显示第20行以及各前后5行的代码
(gdb) list 函数名? ? ? ? ? ? // 显示“函数名”所在函数的源代码
12.查看内存
x命令即 examine 检查货询问内存,有几种不同的方式
(gdb) x [Address]
(gdb) x/[Format] [Address]
(gdb) x/[Length][Format] [Address]
[address]为 想查看的初始地址,整体格式为 x/nfu [addr]
n? 重复的个数,是一个十进制的整数,默认为1,单位为下面的u代表的单位。代表显示多少内存的数据。
f? ?显示的格式,默认是 x 即十六进制,这个显示格式与print格式相似,s代表显示字符串,i代表显示机器指令。
u? 单位大小,b 代表字节,h 代表2个字节(16位),w代表4个字节(32位),g代表8个字节(64位)
参考文献:
1.?GDB, The GNU Debugger, By Example - Cprogramming.com
2.?https://www.cs.umd.edu/~srhuang/teaching/cmsc212/gdb-tutorial-handout.pdf