1、gdb调试过程:
介绍:gdb不仅可以用来调试分析和解决实际问题,也可以用来学习程序运行的过程;
gdb的实现是靠ptrace,让被调试的程序作为gdb的子进程,有的通过gdb fork生成,
有的通过gdb attach收养,因此被调试子程序的所有信号和状态都可以被父进程监听和控制;
1)判断一个程序(可执行文件)是否带有调试信息:
gdb helloworld // helloworld表示要调试的可执行文件
如果出现no debugging symbols found表示该程序没有调试信息;
2)编译生成带调试信息的程序:
gcc -g // 编译时加上-g参数即可保留程序中的调试信息
3)开始调试:
gdb helloworld
然后就是用各种gdb命令来协助调试;
如run, next, step,break, bt, set args, show args, watch ...
2、core文件调试过程:
介绍:程序因为异常或bug造成crash可以产生core文件,通常core文件包含了程序运行时内存、
寄存器状态、堆栈指针、内存管理信息以及函数调用堆栈信息。core就是程序当前工作状态存储生成的一个文件,
通过工具分析这个文件,可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题点并解决。
1)查看coredump是否开启:
ulimit -c
如果为0表示coredump被关闭,通过如下设置开启:
ulimit -c unlimited
插一句:在windows系统cygwin下使能coredump还需要如下一步:
export CYGWIN="$CYGWIN error_start=dumper.exe -d %1 %2" // 添加到.bashrc或当前shell下运行
2)生成core文件:
./helloworld // 执行helloworld程序,如果程序异常crash就会在当前目录生成helloworld.core文件
3)利用core文件调试:
gdb helloworld helloworld.core
然后就可以用gdb的命令来查看和分析问题,常用的如bt来查看堆栈信息;
3、未涉及内容:
1)gdb具体命令的使用和操作方法;
2)gdb如何调试已运行的程序?gdb attach命令到已经运行的程序pid,即把运行程序pid收养到gdb进程下面;
3)已运行的程序没有调试信息,怎么调试?用同样的代码编译一份带调试信息的程序,
然后gdb file命令去读取重新编译好的程序中的调试的信息;
4、gdb命令使用:
gdb命令很多,学习时自己尝试运行一遍加深理解;
1)查看设置的断点:
info b // 或info breakpoints
2)设置断点:
a)b line // 如b 9
b)b file:line // 如b test.c:9
c)b line if reg // 如b 9 if a==10
d)condition 3 a==20 // 修改断点属性,修改3号断点的条件为a==20
e)b function // 对所有定义的函数名称中包含function的函数设置断点
f)rbreak file:. // 规则断点,对文件file中所有定义的函数设置断点
g)rbreak file:print // 规则断点,对文件file中所有定义的函数名称中包含print的函数设置断点
h)tbreak 10 // 临时断点,只会跑1次,后面就会失效
i)ignore 1 30 // 修改断点属性,修改1号断点忽略前面调用的30次
j)watch var // 添加观察点,当变量var值发生改变时暂停并打印前后变化值,需要先运行才能添加
k)rwatch var // 添加观测点,当变量var被读取时(read)暂停
l)awatch var // 添加观测点,当变量var被读或写时(access)暂停
3)开关断点:
a)disable // 关掉所有断点
b)disable bnum // 关掉断点号为bnum的断点
c)enable // 开启所有断点
d)enable bnum // 开启断点号为bnum的断点
4)清除断点:
a)clear // 清除所有breakpoints
b)clear function // 清除所有函数名为function的断点
c)clear file:function // 清除文件file中所有函数名为function的断点
d)clear line // 清除行号line对应的断点
e)clear file:function:line // 清除文件file中函数function中行号line对应的断点
f)delete // 清除所有breakpoints, watchpoints, catchpoints
g)delete bnum // 清除断点号为bnum的断点
5)查看变量:
a)print var 或 p var // 查看变量var的值
b)p point // 查看指针point的地址
c)p *point // 查看指针point指向的内容
d)p *point@10 // 查看指针point指向的10组内容,如打印数组中的数据
e)p $ // $表示上一个变量,这里可以打印上一个变量的值
f)p *$.next // 如果上一个变量是链表指针并且有next成员指针,可以用来打印next指向的内容
g)set $i=0 // 定义环境变量$i为0
p array[$i] // 打印数组array[0]的数据
p array[$i++] // 打印数组array[0]的数据,并且环境变量$i++累加为1
6)按格式查看变量:
p/[f] var // 按格式查看,如p/x var,按十六进制查看变量var的值
格式f:
x 按十六进制格式显示变量
d 按十进制格式显示变量
u 按十六进制格式显示无符号整型
o 按八进制格式显示变量
t 按二进制格式显示变量
a 按十六进制格式显示变量
c 按字符格式显示变量
f 按浮点数格式显示变量
7)查看内存:
x/[n][f][u] addr
n表示内存单元长度,默认为1
f表示打印格式,即x,d,u,o,t,a,c,f
u表示打印的单元类型:
b:字节,
h:半字,2字节
w:字,4字节
g: 8字节
8)自动显示变量内容
a)display var // 添加变量var自动显示,当运行到任意断点暂停时会自动打印变量的值
b)info display // 查看已经添加的自动显示的变量
c)disable display dnum // 禁用第dnum号自动显示变量
d)enable display dnum // 使能第dnum号自动显示变量
e)delete display dnum // 删除第dnum号自动显示变量
9)查看寄存器:
info r // 或info register
10)执行程序相关命令:
a)run // 运行程序
b)n [num] // 执行下一条或下几条语句,一般用在断点暂停后
c)s // 单步进入,如果是函数调用则可以进入函数,否则与n命令功能相同
show step-mode // 查看单步模式,如果遇到没有调试信息的函数是否跳过
set step-mode on/off // 设置不跳过/跳过,当不跳过时进入了函数后可通过finish跳出
d)si // 执行下一条机器指令
e)c [num] // 继续运行直到下一次或下几次断点发生
f)u line // 继续运行到指定行,相当于tb line再c,即添加临时断点再继续运行
g)skip function func // 跳过函数func的执行,这样s单步就会进入函数func了
h)skip file file.c // 跳过文件file.c中的所有函数,这样文件file.c中所有函数都不会进入了
info skip // 查看所有添加的skip
skip disable [snum] // 禁用snum号对应的或所有skip
skip enable [snum] // 使能snum号对应的或所有skip
skip delete [snum] // 删除snum号对应的或所有skip
11)查看源码:
a)l // 或list,默认查看10行代码,需要执行l可以查看下面10行
b)l +/- // 查看下一页或上一页的10行代码
c)l line // 查看行line附近的10行代码,一般是line前面5行,后面5行
d)set listsize 20 // 设置list一页可以显示的代码行数
e)show listsize // 查看list一页可以显示的代码行数,默认是10行
f)l first,last // 查看first到last行之间的代码
g)l file:line // 查看文件file中line行附近的代码
h)l function // 查看函数function开始的代码
i)l file:function // 查看文件file中函数function开始的代码
j)l file:first,file:last // 查看文件file中first到last行之间的代码
k)dir path // 指定源码路径,如果需要查看的文件不在当前目录,则可以添加搜索路径
12)编辑源码:
a)edit line // 编辑第line行开始的源码
b)edit function // 编辑函数function开始的代码
c)edit file:line // 编辑文件file中函数line行附近的代码
d)edit file:function // 编辑文件file中函数function开始的代码
13)执行shell命令:
shell cmd // 需在命令前加上shell
如: (gdb) shell pwd // 查看当前工作目录
(gdb) shell ls -l // list当前目录
(gdb) shell vim file.c // 用vim打开文件file.c
14)高级应用:
info thread // 查看线程信息
...