GDB调试需要特别注意工作目录,否则可能断点命中不了!!
可以info break 看下address 是不是pending
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y <PENDING> Depth_Analysis_Adapter.cpp:300(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00007f4973085a85 in Depth_Analysis_Adapter::TimeToFinish(uint32, uint32)
at ./Depth_Analysis_Adapter.cpp:300
多线程下禁止线程切换:set scheduler-locking on
或指定线程断点
b location t tid //b CConnect::UnBind(bool)if ( this == 0 ) t 77
如果循环次数很多,如何执行完当前的循环?(until)
*指定程序直到退出当前循环体: (没搞明白用法)
(gdb) until
或(gdb) u
这里,发现需要把光标停止在循环的头部,然后输入u这样就自动执行全部的循环了。
*启动gdb,并且分屏显示源代码:
$gdb -tui
这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p.gdb -p pid -tui
效果很完美
info 显示与该程序有关的各种信息
info func 显示所有的函数名称。
info break 显示当前断点清单,包括到达断点处的次数等。
info breakpoints [N]
info break [N] 带参数N的'info break'命令只显示由N指定的断点的信息。
info watchpoints [N]
显示所有的断点和观察点的设置表,有下列一些列
*Breakpoint Numbers*----断点号
*Type*----断点类型(断点或是观察点)
*Disposition*---显示断点的状态
*Enabled or Disabled*---使能或不使能。'y'表示使能,'n'表示不使能。
*Address*----地址,断点在你程序中的地址(内存地址)
*What*---地址,断点在你程序中的行号。
如果断点是条件断点,此命令还显示断点所需要的条件。
info files 显示被调试文件的详细信息。
info local 显示当函数中的局部变量信息。
info prog 显示被调试程序的执行状态。
info var 显示所有的全局和静态变量名称。
print EXPR 显示表达式 EXPR 的值。
p i -> 打印变量i //print 显示变量或表达式的值
GDB print命令打印字符串全部内容
set print element 0
step 执行下一个源程序行,必要时进入下一个函数
finish -> 退出函数
breakpoint 在程序中设置一个断点
b n -> 打断点,在n行//break NUM 在指定的行上设置断点。为已存在断点添加命中条件
使用 condition N condition. N是一个 breakpoint number.
(gdb) help condition
Specify breakpoint number N to break only if COND is true. Usage is `condition N COND', where N is an integer and COND is an expression to be evaluated whenever breakpoint N is reached.
(gdb) condition 1 i == 4
b func -> 打断点,在函数func处
当你的多个文件中可能含有相同的函数名时必须给出文件名。
break FILENAME:FUNCTION
在文件名为FILENAME的FUNCTION函数上设置断点break FILENAME:LINENUM 在文件名为FILENAME的原文件的第LINENUM行设置断点
条件断点: break line-or-function if expr
例:
(gdb) break 46 if testsize==100
(gdb) b 函数名称 if a==5//整数类型
(gdb) b 函数名称 if 0==strcmp(a,"abcdefg") //字符串类型比较break +OFFSET
break -OFFSET
在当前程序运行到的前几行或后几行设置断点break
当break命令不包含任何参数时,break命令在当前执行到的程序运行栈中的
下一条指令上设置一个断点。除了栈底以外,这个命令使程序在一旦从当前
函数返回时停止。相似的命令是finish,但finish并不设置断点。这一点在
循环语句中很有用。gdb在恢复执行时,至少执行一条指令。ignore BNUM COUNT
设置第BNUM号断点的被忽略的次数为'COUNT',即断点BNUM再执行到第COUNT+1
次时程序停止tbreak ARGS 或者简写为 tb
设置断点为只有效一次。ARGS的使用同break中的参量的使用break *ADDRESS
在地址ADDRESS上设置断点,这个命令允许你在没有调试信息的程序中设置断点hbreak ARGS
设置一个由硬件支持的断点。这个命令的主要目的是用于对EPROM/ROM程序的调试
因为这条命令可以在不改变代码的情况下设置断点。这可以同SPARCLite DSU一起
使用。当程序访问某些变量和代码时,DSU将设置“陷井”。注意:你只能一次使用
一个断点,在新设置断点时,先删除原断点thbreak ARGS'
设置只有一次作用的硬件支持断点rbreak REGEX
在所有满足表达式REGEX的函数上设置断点。这个命令在所有相匹配的函数上设置无
条件断点,当这个命令完成时显示所有被设置的断点信息。这个命令设置的断点和
break命令设置的没有什么不同。当调试C++程序时这个命令在重载函数上设置断点时
非常有用。
非常感谢GDB常用命令集锦_Phoenix_FuliMa-CSDN博客的分享,太棒了!!
watch 在程序中设置一个监测点(即数据断点) //GDB将把表达式加入到程序中并监
视程序的运行,当表达式的值被改变时GDB就使程序停止。 for、 whileWatchpoint 15 deleted because the program has left the block in
rwatch EXPR'
设置一个观察点,当EXPR被程序读时,程序被暂停。在多线程的程序中,观察点的作用很有限,GDB只能观察在一个线程中的表达式的值,如果你确信表达式只被当前线程所存取,那么使用观察点才有效。GDB不能注意一个非当前线程对表达式值的改变。
awatch EXPR' //access watch
设置一个观察点,当EXPR被读出然后被写入时程序被暂停。
maint info breakpoints
显示所有的断点,无论是你设置的还是gdb自动设置的。
断点的含义:
breakpoint:断点,普通断点
watchpoint:普通观察点
longjmp:内部断点,用于处理'longjmp'调用
longjmp resume:内部断点,设置在'longjmp'调用的目标上
until:'until'命令所使用的内部断点
finish:finish'命令所使用的内部断点
clear 删除设置在特定源文件、特定行上的断点。
只有clear则是删除当前行断点,如果有的话。
其用法为clear FILENAME:NUM
*删除所有断点:
(gdb) deletedelete 删除指定索引的断点 delete 0
info break显示 #0 #1 #2
list 显示源代码段。
list 列出相应于正在执行的程序的原文件内容
next 在不单步执行进入其他函数的情况下,向前执行一行源代码。
n -> 执行下一行,单挑执行 //
*执行N次下一步:
(gdb) next N
*执行上次执行的命令:
(gdb) [Enter]
这里,直接输入回车就会执行上次的命令了。
backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)
bt -> 查看函数堆栈 //bt 显示所有的调用栈帧。该命令可用来显示函数的调用顺序。
up 上移栈帧,使另一函数成为当前函数
down 下移栈帧,使得另一个函数成为当前函数
continue 继续执行正在调试的程序。
该命令用在程序由于处理信号、刚刚挂载进程 或断点而 导致停止运行时。
run 执行该程序
r -> 运行程序 //
quit 退出gdb
q -> 结束调试 //
常用命令(From:http://my.donews.com/tangfl/2006/10/23/gdb-debug-example/)
display EXPR 每次程序停止后显示表达式的值。表达式由程序定义的变量组成。
file FILE 装载指定的可执行文件进行调试。
help NAME 显示指定命令的帮助信息。
kill 终止正被调试的程序。 //kill 异常终止在gdb 控制下运行的程序
make 在不退出 gdb 的情况下运行 make 工具。
cd 改变当前工作目录
commands 命中断点时,列出将要执行的命令
display 程序停止时显示变量和表达时
frame 选择下一条continue命令的帧
jump 在源程序中的另一点开始运行
pwd 显示当前工作目录
pype 显示一个数据结构(如一个结构或C++类)的内容
reverse-search 在源文件中反向搜索正规表达式
search 在源文件中搜索正规表达式
set variable 给变量赋值
signal 将一个信号发送到正在运行的进程
undisplay display命令的反命令,不要显示表达式
until 结束当前循环
whatis 显示变量或函数类型
x /nxb -> 以单字节(b)为单位,以十六进制形式显示(x),打印n(n)个字节。
*跳转执行程序到第5行:
(gdb) jump 5
这里,可以简写为"j 5"需要注意的是,跳转到第5行执行完毕之后,如果后面没有断点则继续执行,而并不是停在那里了。
另外,跳转不会改变当前的堆栈内容,所以跳到别的函数中就会有奇怪的现象,因此最好跳转在一个函数内部进行,跳转的参数也可以是程序代码行的地址,函数名等等类似list。
*强制返回当前函数:
(gdb) return
这样,将会忽略当前函数还没有执行完毕的语句,强制返回。return后面可以接一个表达式,表达式的返回值就是函数的返回值。
*强制调用函数:
(gdb) call <expr>
这里,<expr>可以是一个函数,这样就会返回函数的返回值,如果函数的返回类型是void那么就不会打印函数的返回值,但是实践发现,函数运行过程中的打印语句还是没有被打印出来。
*查看当前调试程序的语言环境:
(gdb) show language
这里,如果gdb不能识别你所调试的程序,那么默认是c语言。
*查看当前函数的程序语言:
(gdb) info frame
*显示当前的调试源文件:
(gdb) info source
这样会显示当前所在的源代码文件信息,例如文件名称,程序语言等。
*手动设置当前的程序语言为c++:
(gdb) set language c++
这里,如果gdb没有检测出你的程序语言,你可以这样设置。
*查看可以设置的程序语言:
(gdb) set language
这里,使用没有参数的set language可以查看gdb中可以设置的程序语言。
*终止一个正在调试的程序:
(gdb) kill
这里,输入kill就会终止正在调试的程序了。
*用16进制显示(var)值:
(gdb) print /x var
这里可以知道,print可以指定显示的格式,这里用'/x'表示16进制的格式。
可以支持的变量显示格式有:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
*如果a是一个数组,10个元素,如果要显示则:
(gdb) print *a@10
这样,会显示10个元素,无论a是double或者是int的都会正确地显示10个元素。
*修改运行时候的变量值:
(gdb) print x=4
这里,x=4是C/C++的语法,意为把变量x值改为4,如果你当前调试的语言是Pascal,那么你可以使用Pascal的语法:x:=4。
*显示一个变量var的类型:
(gdb) whatis var
*以更详细的方式显示变量var的类型:
(gdb) ptype var
这里,会打印出var的结构定义。
**没有实践过的
*print显示存储块,如显示h后面的10个整数:
print h@10
https://www.cnblogs.com/zhoug2020/p/7283169.html
3.cont N
第N次经过该断点时才停止程序运行
4.enable 断点编号
恢复暂时失活的断点,要恢复多个编号的断点,可用空格将编号分开
5.disable 断点编号
使断点失效,但是断点还在
附加到进程调试:
gdb ../bin64/h5svr -p pid 别忘记c继续程序哦
gdb启动程序并带参数
gdb ../bin64/h5svr
gdb) set args [-start mainsvr ] -f xxx.xml -c
gdb) run
$ gdb --args ../bin.x64/h5svr -start mainsvr -f xxx.xml -c
(gdb) run -start mainsvr -f xxx.xml -c
保存
(gdb) save breakpoint xxxx.bp
恢复
(gdb) source xxxx.bp(实际上就是gdb脚本)
http://sourceware.org/gdb/current/onlinedocs/refcard.pdf.gz
http://sourceware.org/gdb/documentation/
-g编译的程序去掉编译的调试信息,可以用strip a.exe
print /x /d /u /o /t(二进制) /f /c(字符形式)
ptype 打印变量类型
whatis 变量或表达式 ------- 显示变量或表达式的数据类型
(gdb) whatis buf
type = char [3]
(gdb) ptype buf
type = char [3]
修改变量的值 p data = 100
p data 打印显示100
set variable 变量=值 ------ 给变量赋值
(gdb) set buf[0]='a'
(gdb) p buf
$1 = "a\345\377"
(gdb) p buf[1]='b'
$2 = 98 'b'
(gdb) p buf
$3 = "ab\377"
(gdb)
打印全局变量 p 'xxx.cpp'::st_um
打印内存块内容,如果只用print *pData则只能打印一个pData类型的内存块,如果是char*则是一个字符,如果是char*[10] 类型则是10个字符。下面假设其是char* pData
要打印一段内容需要使用 print *pData@length eg: p *pData@20
(加餐,gdb默认最多打印200字符,要打印超过200个字符需要先 设置 set print elements 0,然后再调用 p *pData@210 打印内存块中的210个字符)——置为0表示没有限制
examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:
x/<n/f/u> <addr>
n、f、u是可选的参数。
n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义。
f 表示显示的格式,参见下面。如果地址所指的是字符串,那么格式可以是s,如果是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字 节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
<addr>表示一个内存地址。
注意:严格区分n和u的关系,n表示单元个数,u表示每个单元的大小。
n/f/u三个参数可以一起使用。例如:x/10tb buf
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示输出三个单位,u表示按无符号十进制显示。
监视点变量或监测变量设置 watch data
rwatch data (data值被读取则中止)和 awatch =(watch + rwatch)读写则中止
删除变量检测
(gdb) info watch
Num Type Disp Enb Address What
2 hw watchpoint keep y buf
breakpoint already hit 2 times
(gdb) delete 2
(gdb) info watch
No watchpoints.
watch变量的使能和不能设置
(gdb) watch buf
Hardware watchpoint 3: buf
(gdb) info watch
Num Type Disp Enb Address What
3 hw watchpoint keep y buf
(gdb) disable 3
(gdb) info watch
Num Type Disp Enb Address What
3 hw watchpoint keep n buf
(gdb) enable 3
(gdb) i watch
Num Type Disp Enb Address What
3 hw watchpoint keep y buf
(gdb)
enable once 3使能一次,触发后disable
enable delete 3 使能,触发后删除
观察点设置,观察变量 display data
watch和display设置监測点的差别:
watch监測仅仅有当监測的变量值发生变化时才显示变量,并且旧值和新值都会显示。
display监測每一次执行命令都会显示变量的值,仅仅会显示变量的最新值。
查看和删除display
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
1: y buf
(gdb) undisplay 1
不能和使能display
(gdb) display buf
2: buf = 0x7fffffffe4e0
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2: y buf
(gdb) disable display 2
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2: n buf
(gdb) enable display 2
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2: y buf
设置条件断点 break filenum if condi==2
忽略断点n次 ignore
info break
$1xxxx
$2 xxx
ignore 2 10 //忽略断点命中10次
next 单步执行程序,遇到函数调用不会进入
step 单步执行程序,遇到函数调用会进入
next cnt 一次执行多步
step cnt 一次执行多步,会进入函数
nexti // nexti/stepi --------------- 单步运行一条机器指令
(gdb) ni
0x00000000004005c9 11 printf("44\n");
(gdb) n
44
12 print();
stepi 指令形式执行
(gdb) si
0x00000000004005a6 4 printf("xxxx");
(gdb)
0x00000000004005ab 4 printf("xxxx");
(gdb)
0x0000000000400470 in printf@plt ()
until ====循环体最后一句时,执行完循环后在循环外停止
until line ====停止在某行
jump location 可以修改代码执行逻辑,执行原本不可能执行到的代码,
(gdb) jump print()
Line 4 is not in `main()'. Jump anyway? (y or n) y
Continuing at 0x4005f1.
Breakpoint 1, print () at main.cpp:4
4 printf("xxxx");
(gdb) jump 4
Line 4 is not in `main()'. Jump anyway? (y or n) y
Continuing at 0x4005f1.
Breakpoint 1, print () at main.cpp:4
4 printf("xxxx");
finish 立即执行完函数后返回
return直接返回,不会执行下面的代码,可以指定函数返回值
disassemble
查看栈信息 bt (backtrace)
$1 ssss休息休息
$2 xxxx西溪湿地
切换栈编号 frame 2
$2 xxxx西溪湿地
===========gdbserver =============
server端启动
[root@VM-4-7-centos ~]# gdbserver 127.0.0.1:8818 a.out
或gdbserver 127.0.0.1:8818 attach 28678
Process a.out created; pid = 28678
Listening on port 8818
Remote debugging from host 127.0.0.1
print %
Detaching from process 28678
客户端启动
[root@VM-4-7-centos ~]# gdb
(gdb) target remote 127.0.0.1:8818
Remote debugging using 127.0.0.1:8818
warning: Could not load vsyscall page because no executable was specified
0x00007ffff7ddc140 in ?? ()
(gdb) l
No symbol table is loaded. Use the "file" command.
(gdb) file a.out
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from /root/a.out...done.
(gdb) l
1 #include <stdio.h>
2
3 int main(){
4 int a = 100;
5 printf("print %%\n");
6 return 0;
7 }
(gdb) b 5
Breakpoint 1 at 0x40056c: file m.cpp, line 5.
(gdb) c
Continuing.
Breakpoint 1, main () at m.cpp:5
5 printf("print %%\n");
(gdb) n
6 return 0;
(gdb) detach
Detaching from program: /root/a.out, process 28678
Ending remote debugging.
[Inferior 1 (process 28678) detached]
(gdb) quit
============================================
4、gdb选项(gdb中好多命令都有自己的简写字母):
不输入直接回车 ------------ 反复运行上一条命令
q(quit) ------------------- 退出gdb
file filename ------------- 打开文件filename
l(list) ------------------- 显示10行代码。若再次执行则显示接下来10行代码
list 5,10 ---------------- 显示第5到10行的代码
list test.c:5,10 -------- 显示源文件test.c中第5到10行的代码
list get_sum -------------- 显示get_sum函数周围的代码
list test.c:get_sum ------- 显示源文件test.c中get_sum函数周围的代码
shell XXX ----------------- 执行shell命令XXX
search/forward str -------- 从当前行向前查找第一个匹配的字符串str
reverse-search str -------- 从当前行向后查找第一个匹配的字符串str
r(run) -------------------- 执行程序
help XXX ------------------ 查看命令XXX的用法
help all ------------------ 查看全部命令的用法
whatis 变量或表达式 ------- 显示变量或表达式的数据类型
set variable 变量=值 ------ 给变量赋值
kill ---------------------- 结束当前程序的调试
continue ------------------ 让程序继续执行,直到下一个断点或者执行完为止
n(next) ------------------- 继续运行下一条语句,遇到函数把函数当作一条语句来运行
step ---------------------- 继续运行下一条代码,遇到函数会跟踪进入函数
nexti/stepi --------------- 单步运行一条机器指令
watch 变量名 -------------- 设置变量监測点
bt(backtrace) ------------- 显示程序当前执行位置和对当前位置的栈跟踪
display 变量或表达式 ------ 加入观察点。以后每次执行命令都会显示相应变量或表达式的值
undisplay num ------------- num为设置的display编号,能够用info display获取。不能用变量名
5、设置断点:
b(break) 行号 ----------------------- 在第n行设置断点
break fun_name ---------------------- 为函数fun_name设置断点
break 行号或函数名 if 条件 ---------- 程序在执行中。当条件满足时。在某行中断暂停执行
watch 条件表达式 -------------------- 程序执行中,满足条件时暂停执行,不须要写行号
info breakpoints -------------------- 查看当前全部的断点
disable 断点编号 -------------------- 使断点n失效
enable 断点编号 --------------------- 使断点n有效
clear ------------------------------- 删除本行断点(假设存在的话)
clear 行号 -------------------------- 删除此行断点
clear 函数名 ------------------------ 删除该函数的断点
delete 断点编号 --------------------- 删除指定编号的断点
6、print命令:
print XXX ------------------------------- 打印输出XXX的值
print 变量 = 值 ------------------------- 对变量赋值
print 表达式@要打印值的个数n ------------ 打印以表达式值開始的n个数
7、watch和display设置监測点的差别:
watch监測仅仅有当监測的变量值发生变化时才显示变量,并且旧值和新值都会显示。
display监測每一次执行命令都会显示变量的值,仅仅会显示变量的最新值。