目录
安装
mac下需要授权,不然不能使用
gbd帮助信息
- 进入gdb,显示所有帮助信息:help
- 针对1中显示的某项,显示所有的帮助信息:help breakpoints
启动退出gdb
启动:
- gcc –g file.c
- gdb a.out 或者 gdb,file a.out
退出:q
显示源文件
- 不能正常显示源文件
解决方案: run一遍程序 - 设置一次显示的源码行数:set listsize 数字。显示刚才的设置:show listsize
- 显示程序源码:list(l)
- 不加参数[当前行后面]
- 上次显示源码的第一行的前面listsize行:-
- 上次显示源码的最后一行的后面listsize行:+或者不加参数
- 上次显示源码中间那行减offset行开始,之后的listsize行:-offset
- 上次显示源码中间那行加offset行开始,之后的listsize行:+offset
- 开始行号[开始行号为空,表示从当前行开始],结束行号
- 文件名:行号
- 文件名:函数名
- 函数名
- 搜索关键字:search 正则表达式
- 显示当前程序执行到哪一句
where
设置程序启动时的命令行参数
1 直接跟在run后面
(gdb) run arg1 arg2 …
2 用命令,以后运行程序时都是这些参数
(gdb) set args arg1 arg2 …
清空2设置的args参数,为了运行不带命令行参数的程序
(gdb) set args
segment fault和源程序assert造成的程序运行中断
中断时,是不能打印变量的信息的,因为不是处于用户层程序处。
解决方法:
- bt显示栈帧
- 使用frame 1/2/3…切换到用户层栈帧处
- 就可以通过打印栈帧中的变量
打印动态分配的指针的空间大小
介绍几个关于C/C++程序调试的函数_rhdfcgj_新浪博客
malloc_usable_size(p)
查看某个函数被谁调用的过程
- 在函数内部设置断点
- 断点处输入bt打印被谁调用
- 重复观察该断点处的bt情况
断点
- 增加断点:
- 在某一行设置断点:break 行号
- 函数定义处设置断点:break 函数名
- 条件断点:b 行号 if strcmp(指针a,”temp”)==0。效果:指针a所指字符串等于temp时,在行号处插入断点并中断。tip:tab键不能自动补全,自己确认输入的正确就行了。
- 删除断点:delete(d) 断点编号[不加该参数默认删除所有断点,该参数使用显示断点命令显示的Num号]
- 显示断点信息:info break
- 禁用断点
- 禁用特定的断点
disable breakpoint 断点编号 - 禁用所有的断点
disable
- 禁用特定的断点
- 打开断点
- 打开指定的断点
enable breakpoint 断点编号 - 打开所有断点
enable
- 打开指定的断点
- 执行到某个断点处
观察点
- 功能:运行到断点处,在该断点处设置某一个变量为观察点。然后continue命令会在断点或者观察点的值发生变化时,中断。
- 增加观察点:
- 对要观察的变量处设置断点
- 运行到断点处
- 在断点处设置观察点: watch 变量名。设置完观察点后不用删除该变量所在行的断点
- continue就会在该变量的值发生变化时停下来
- 显示观察点:info(或i) watchpoints
- 删除观察点:delete 该Num号(显示观察点命令显示的观察点有个Num序号)
- 规律:重新run之后,设置的观察点消失
程序执行流程控制
- 没有断点运行完整程序,有断点运行到第一个断点处:run(r) [命令行参数1] [命令行参数2]
- 执行run命令之后使用,运行到下一个断点:continue(c)
- 执行run命令之后使用,执行下一条指令(不进入函数):next(n).
n 3,执行3条 - 执行下一条指令(进入函数):step(s)。退出被调用函数:finish(f)
- 在函数内部跳出函数
finish - 跳转到指定行号处执行
- 先在要跳转到的指定行号处设置断点!!!
- jump 指定行号
查看程序运行状态
- 打印指针变量内容:print(p) 指针变量名
- 打印指针变量指向变量的内容:print(p) *指针变量名
- 查看变量类型:ptype或者whatis 变量名
- 查看堆栈:backtrace(bt),然后用frame 号 查看某一层栈
- 查看系统变量:print(p)系统变量名
- $pc : 程序计数器
- $fp : 帧指针(当前堆栈帧)
- $sp : 栈指针
- $ps : 处理器状态
多进程多线程调试
想要调试多线程,必须先插入断点,让程序在断点处中断。
- 如果在main函数的第一行,插入断点。info threads显示只有main进程。
- 如果运行到第一个pthread_create之后。info threads显示main线程和该thread。
- 如果运行到第二个pthread_create之后。info threads显示main线程、thread、该thread。
插入断点
b 行号
设置调试进程和线程模式(可选)
只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。
detach-on-fork(是否同时调试父进程和子进程) | follow-fork-mode(调试父进程或者子进程) | 说明 |
---|---|---|
on | parent | 只调试主进程(GDB默认) |
on | child | 只调试子进程 |
off | parent | 同时调试两个进程,gdb跟主进程,子进程block在fork位置 |
off | child | 同时调试两个进程,gdb跟子进程,主进程block在fork位置 |
设置方法:set follow-fork-mode [parent|child] set detach-on-fork [on|off]
调试进程
使用top查看杀死上次调试的进程
在fork位置处中断
catch fork
catch event
Stop when event occurs. event can be any of the following:
throw
The throwing of a C++ exception.
catch
The catching of a C++ exception.
exec
A call to exec. This is currently only available for HP-UX.
fork
A call to fork. This is currently only available for HP-UX.
vfork
A call to vfork. This is currently only available for HP-UX.
显示进程信息
info inferiors
切换调试的进程
inferior
添加新的调试进程
add-inferior [-copies n] [-exec executable] ,可以用file executable来分配给inferior可执行文件。
其他
remove-inferiors infno, detach inferior
调试线程
显示线程信息
- 线程ID,后面用来切换线程
每个线程执行到哪一句
显示所有线程的信息
info threads
显示某个线程的信息
info threads 线程ID
只调试某一线程,切换到线程
thread threadID
断点
断点对所有线程生效
break
断点对指定线程生效
break thread
线程执行顺序控制
进程间执行顺序控制
只让当前被调试线程执行
set scheduler-locking on
不锁定任何线程,也就是所有线程都执行,这是默认值
set scheduler-locking off
在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行
让所有被调试线程执行GDB命令command
thread apply ID1 ID2 command
让一个或者多个线程执行GDB命令commandthread apply all command
让所有被调试线程执行GDB命令command中断UI进程
C-c 中断的是gdb的UI进程。后台如果有死锁的进程在运行,那么还像以前一样运行。
Finding multi-threading bugs with gdb中断每一个在运行的进程,看看他们在做什么
(gdb) interrupt -a
(gdb) bt
cont
显示某线程执行处的代码
- 先切换到线程上。
- 然后l
l显示的是当前线程执行处的代码
调试实例
分析死锁
Finding multi-threading bugs with gdb
调试多进程和多线程
gdb调试多进程和多线程命令 - 高科的专栏 - 博客频道 - CSDN.NET
遇到的问题
子线程在正常运行模式下不打印信息,在gdb下打印
原因是,正常运行模式下main线程运行的快
其他使用方法
- ctrl+r 搜索输入历史
- 自动补全输入的命令:CapsLock建
- 重复执行上一条命令:回车
- 显示输入历史:上方位键
- 输入命令的缩写形式
- gdb脚本
- 启动gdb时候
gdb在启动的时候,会在当前目录下查找”.gdbinit”这个文件,并把它的内容作为gdb命令进行解释,所以如果我把脚本命名为”.gdbinit”,这样在启动的时候就会处理这些命令。 - gdb运行期间
可以使用 source script-file 来解释gdb命令脚本script-file
把设置参数set args等下入下面文件,启动gdb就行
.gdbinit - 语法
define nn
n
l
end
在gdb里,输入nn,程序执行到下一句,并显示语句
- 启动gdb时候