gdb的一些常用用法
gdb笔记
gdb的命令非常多,以下是在整理网上的几篇文章并结合自己的实践的基础上,罗列一些常用的用法,包括了多线程和多进程的调试。
- Linux命令行运行
- gdb -q 进入gdb,不打印版本信息
- gdb <program> 直接装载程序,但没有运行
- gdb <program> <core_file> 该core文件是该program非法执行后dump出的
- gdb -d 加入一个源程序搜索路径
- 挂接正在运行的程序
- gdb
- gdb attach
- detach 取消挂接
- gdb中运行的常用命令
- help 查看帮助信息
- file 进入gdb之后再装载程序
- set 可指定运行参数,类似于 run 但没有立即run
- show args 查看设置好的运行参数
- next 或 n 不进入函数,仅把函数调用当成一条语句执行
- step 或 s 进入函数
- nexti 或 stepi 执行一条机器指令
- finish 运行程序,直到当前函数完成返回;并打印函数返回时的堆栈地址和返回值及参数值等信息。
- until 或 u 当不想在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
- shell <shell_command> 即可运行shell命令
- set environment = 设置环境变量
show environment
show environment
unset environment
- 查看源代码
- list - 显示当前行前面的源程序。
- set listsize 设置一次显示源代码的行数。
- show listsize 查看当前listsize的设置。
- directory <dirname … > = dir <dirname … > 指定源文件的路径
加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可以使用“:”,Windows下你可以使用“;”。 - directory 清除所有的自定义的源文件搜索路径信息。
- show directories 显示定义了的源文件搜索路径。
- 恢复/暂停程序在gdb中,有以下几种暂停方式。如果要恢复程序运行,可以使用c或是continue命令。
- 断点(BreakPoint)
- 观察点(WatchPoint)
- 捕捉点(CatchPoint)
- 信号(Signals)
- 线程停止(Thread Stops)。
5.1 断点
- info breakpoints
- break
- break
- break <line/function> if
- clear 删除所有断点
- clear
- clear
- delete 删除该断点编号的断点
- disable 暂时失效
- enable 再次使能
5.2 watch(观察点)
- info watchpoints
- watch 为表达式或变量设置一个观察点,一旦表达式值有变化时,停住程序
- rwatch 当表达式或变量被读时,停住程序
- awatch 当表达式或变量被读或被写时,停住程序
5.3 捕捉点(CatchPoint)
可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。
设置捕捉点的格式为:
- catch
当event发生时,停住程序。event可以是下面的内容:
- throw 一个C++抛出的异常。(throw为关键字)
- catch 一个C++捕捉到的异常。(catch为关键字)
- 等等
- 查看栈信息
- bt = backtrace
- bt n是一个正整数,表示只打印栈顶上n层的栈信息。
- bt <-n> -n表一个负整数,表示只打印栈底下n层的栈信息。
- gdb变量
可以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量,只需使用GDB的set命令。
GDB的环境变量和UNIX一样,也是以$起头。如:
- set $foo = *object_ptr
使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值。环境变量没有类型,你可以给环境变量定义任一的类型。包括结构体和数组。
- show convenience 该命令查看当前所设置的所有的环境变量。
环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如
set $i = 0
print bar[$i++]->contents
输入这样的命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能。
于是你就不必像下面这样输入命令了。
print bar[0]->contents, print bar[1]->contents
- 信号
可以告诉GDB需要处理哪一种信号。可以要求GDB在收到指定的信号时,立即停住正在运行的程序,以供进行调试。可以用GDB的handle命令来完成这一功能。
handle <signal> <keywords...>
在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO,SIGIOT,SIGKILL三个信号),也可以使用关键字all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其可以是以下几种关键字的一个或多个。
- nostop 当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号。
- stop 当被调试的程序收到信号时,GDB会停住你的程序。
- print 当被调试的程序收到信号时,GDB会显示出一条信息。
- noprint 当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。
- pass
- noignore 当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理。
- nopass
- ignore 当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。
- info signals
- info handle 查看有哪些信号在被GDB检测中。
- 用gdb简单分析死锁
当发生死锁时,进程会僵住,这时只需要杀死进程,让系统产生一个 core dump 文件,然后再对这个 core dump 文件进行分析即可。
比如,系统生成了core dump 文件,放在了/var/crash目录下,此时就可以使用 gdb 进行分析:
gdb /var/crash/<core_dump_file>
然后再:
info threads
thread
bt
即能发现死锁的位置
- 多线程调试
-
info thread 查看当前进程的线程。
-
thread 切换调试的线程为指定ID的线程。
-
break file.c:100 thread all 在file.c文件第100行处为所有经过这里的线程设置断点。
-
thread applay [thread-id-list]/[all] args 在指定的线程上执行特定的命令args.
-
set print thread-events 用于设定是否提示线程启动或停止时的信息。
-
set libthread-db-search-path
指定libthread-db 的路径信息。 -
set scheduler-locking off|on|step
- off 不锁定任何线程,也就是所有线程都执行,这是默认值。
- on 只有当前被调试线程会执行。
- step 阻止其他线程在当前线程单步调试时,抢占当前线程。
只有当next、continue、util以及finish的时候,其他线程才会获得重新运行的机会。
-
non-stop模式
针对“一个线程中断在一个断点上,其他所有的线程都会被freeze”的情况, gdb 7.0引入了non-stop模式,即:除了断点有关的线程会被停下来,其他线程会继续执行。
设置non-stop模式的方法:
运行gdb后,开始run之前,输入下面的指令set target-async 1 set pagination off set non-stop on
- gdb调试多进程
-
follow-fork-mode
set follow-fork-mode parent|child
show follow-fork-modeparent:fork之后继续调试父进程,子进程不受影响。
child:fork之后调试子进程,父进程不受影响。 -
inferior
gdb称任何执行中的进程为inferior- inferior ID:切换到指定的inferior
- info inferiors:列出当前被gdb调试的每个inferior信息
- detach inferior ID:detach指定的inferior,允许其正常运行
上一篇: php定时执行