GDB(GNU Debugger)是在Unix以及类Unix系统下的调试工具。功能极其强大,几乎涵盖了你所需要的全部功能。
GDB主要帮忙你完成下面四个方面的功能:
1.启动你的程序,可以按照你的定制要求随心所欲的运行程序。
2.可让被调试的程序在你所指定的调置的断点处停住。
3.当程序被停住时,可以检查此时你的程序中所发生的事,以及内存状态等。
4.动态的改变你程序的执行环境。
gdb使用总旨:help指令很强大,在gdb里面输入:help all
gdb使用前置条件:
用于编译时加入debug信息,gcc/g++是在编译时加入-g,-g分4个等级:
1)-g0 等于不加-g。即不包含任何信息
2)-g1 只包含最小信息,一般来说只有你不需要debug,只需要backtrace信息,并且真的很在意程序大小,或者有其他保密/特殊需求时才会使用-g1。
3)–g2 为gdb默认等级,包含绝大多数你需要的信息。
4)–g3 包含一些额外信息,例如包含宏定义信息。当你需要调试宏定义时,请使用-g3
常用命令
查看帮助
gdb -> help all
调试程序
在gdb下运行你的程序的三种方法:
1)gdb ${你的程序} -> run(简写r) ${arg1} ${arg2}
2)gdb --args ${你的程序} ${arg1} ${arg2} -> run
3)gdb -> file ${你的程序} -> set args ${arg1} ${arg2} -> run
调试正在运行的程序
gdb ${你的程序} ${程序pid}
查core
gdb ${你的程序} ${core文件}
显示栈信息
backtrace(简写bt)
往栈顶/栈底移动x帧
up/down x(当不输入x时,默认为1)
打印x的信息
print x(简写p)
打印x的内容/地址
print */&x
改变当前变量x的值
set var x=值
继续运行程序
continue (简写c)
执行到当前循环完成
until (简写u)
单步调试(步入当前函数)
step (简写s)
单步调试(步过当前函数)
next (简写n)
执行到当前函数返回
finish
设置监视点
监视点是监视内存中某个地址,当该地址的数据被改变(或者被读取)时,程序交出控制权进入调试器,监视点分为软件模式和硬件模式,默认优先使用硬件监视点。分别有:watch(写监视)、rwatch(读监视)、awatch(读写监视)。
1)(r/a)watch x。x是一个变量名。当x的值改变/被读取时,程序交出控制权进入调试器。
2)(r/a)watch 0xN。N为一个有效地址。当该地址的内容变化/被读取时,程序交出控制权进入调试器。
设置断点
指当执行到程序某一步时,程序交出控制权进入调试器。
1)tbreak与break功能相同,只是所设置的断点在触发一次后自动删除。
2)hbreak是一个硬件断点,硬件断点需要硬件支持。
3)rbreak稍微特殊一些,它会在匹配正则表达式的全部位置加上断点。
用法:
1)(t/h)break x.cpp:y 。在代码x.cpp的第y行加入断点。x.cpp若不指定,则会以当前执行的文件作为断点文件。
2)(t/h)break 0xN。在地址N处加入断点。
3)(t/h)break x.cpp:func。在x.cpp的func函数入口处加入断点。可通过指定参数类型来避免重载,如break func(char *)
4)(t/h)break +/-N。在当前运行处的第N行后/前加入断点。
5)rbreak REGEXP。 在所有符合正则表达式REGEXP的函数入口加入断点。
另外,breakpoints可以通过save命令保存,以方便使用者下次再次进入程序调试时不需要重设断点。
设置跟踪点
tracepoints
只是跟踪记录信息而不会中断程序的运行。
设置检查点
checkpoint
可以保存某一个时间点的程序状态或者说是程序映像,并且稍后又可以返回到这个状态。
每个检查点是进程的一个拷贝,这样当一个bug很难重现时,可以在接近bug出现之前的地方设置一个checkpoint,这样即使debug过头了,也可以从这个checkpoint开始,而不用重启整个程序并且期待它重现这个bug。
注意:每个checkpoint有一个唯一的进程id,这个pid与原始程序的pid不同,因此如果程序需要使用pid的信息时,需要慎重考虑。
调试coredump
core dump 一般是在segmentation fault(段错误)的情况下产生的文件。操作系统在程序发生异常且在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个文件里。
core文件的大小:
临时设置:
ulimit -c 可以设置core文件的大小,如果这个值太则不会产生core文件,因为core文件一般都比较大。使用ulimit -c unlimited可以设置无限大。
永久设置:
在/etc/security/limits.conf 最后加上两行
@root soft core unlimited
@root hard core unlimited
命名规则设置:
永久:
在 /etc/sysctl.conf 最后加上两行:
kernel.core_pattern = /var/core_log/core_%e_%t_%p
kernel.core_uses_pid = 0
调试coredump
gdb打开core文件的格式为
gdb ${你的程序} ${core文件}
查看函数调用栈信息命令:
backtrace(可简写 bt)
向栈的上移 / 下移
up / down
打印更为详细的当前栈层的信息
info frame(可简写 info f)
打印当前函数的参数名及其值
info args
打印当前函数中所有局部变量及其值
info locals
打印当前函数中的异常处理信息
info catch
显示程序第linenum行的周围的源程序
list