主要的调试器操作

一般在使用调试器的时,有些基本的操作,比如:设置断点、检查变量、设置监视点、移动调用栈等等。现在介绍GDB的这些操作。

0x01. 单步调试源代码

在gdb中用run命令运行程序。也可以安排程序的执行在某个地方暂停,以便检查变量的值,从而得到关于程序错误所在的位置线索。下面是可以用来暂停程序执行的一些方法。

  1. 断点
    在gdb中通过break命令及其行号设置断点,主要有4中方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    格式: break function
    说明:在函数function的入口处设置断点。比如:(gdb) break main

    格式:break line_number
    说明:在当前活动源代码文件的line_number出设置断点。比如:(gdb) break 35

    格式:break filename:line_number
    说明:在源代码文件filename的line_number处设置断点。如果filename不在当前工作目录中,则可以给出相对路径名或者完全路径名来帮助gdb查找该文件。比如:(gdb) break source/bed.c:35

    格式:break filename:function
    说明:在文件filename中的函数function()的入口处设置断点。重载函数或者使用同名静态函数的程序可能需要使用这种形式,比如:(gdb) break bed.c:parseAguments

  2. 单步调试
    gdb拥有单步调试的能力,比如next命令让gdb执行下一行,然后暂停。step命令的作用与此类似。两个区别:step是单步进入,即碰到函数调用时,step让gdb进入函数内部一一执行;而next是单步步过,即碰到函数执行时,next让gdb在函数调用的下一条语句暂停,跳过函数的执行。

  3. 恢复操作
    gdb中,continue命令通知调试器恢复执行并继续。还有finish和utill指令。

  4. 临时断点
    在gdb中,tbreak命令与break相似,但是这一命令设置的断点的有效期只到首次到达指定行时为知。

0x02. 检查变量

当调试器暂停了程序的执行后,可以执行一些命令来显示程序变量的值。这些变量可以是局部变量、全局变量、数组的元素和C语言的struct、C++类中的成员变量等。如果发现某个变量有一个出乎意料的值,那往往是找出某个程序错误的位置和性质的重要线索。gdb中可以使用print命令输出当前值:
(gdb) print j

0x03. 设置监视点

监视点结合了断点和变量检查的概念。最基本形式的监视点通知调试器,每当指定变量的值发生变化时都暂停程序的执行。例如。在程序执行期间,假设要在变量z改变值时查看程序的状态。在gdb中,可以执行如下命令:
(gdb) watch z

0x04. 上下移动调用栈

在函数的调用期间,与调用关联的运行时信息存储在称为栈帧(stack frame)的内存区域中。帧中包含函数的局部变量的值、其形参,以及调用该函数的位置的记录。每次发生函数调用时,都会创建一个新帧,并将其推到一个系统维护的栈上;栈最上方的帧表示当前正在执行的函数,当函数退出时,这个帧被弹出栈,并且释放。
在gdb中可以用如下命令查看以前的帧:
(gdb) frame 1
也可以使用backtrace命令显示整个栈,即当前存在的所有帧的集合:
(gdb) backtrace