首页 > 代码库 > gdb调试

gdb调试

调试工具:

GDB

UNIX程序员最常用的调试工具是GDB,大多数Linux系统应该预先安装了GDB。如果没有预先安装该工具,则必须下载GCC编译器程序包。

DDD

随着GUI(图形用户界面)越来越流行,大量的UNIX环境下运行的基于GUI的调试器被开发出来。其中的大多数工具都是GDB的GUI前端:用户通过GUI发出命令,GUI将这些命令传递给GDB。DDD就是其中的一种工具。

如果你的系统还没有安装DDD,则可以下载该工具。例如,centos系统上,命令

yum install ddd

将自动处理整个安装过程。

主要调试器操作

1 单步调试源代码

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

  • 断点

  正如前面所说,调试工具会在指定断电处暂停程序的执行。在GDB中是通过break命令及其行号完成的,在DDD中是在相关代码行的任意空白处右击并选择Set Breakpoint来完成的。

  • 单步调试

  GDB的next命令让GDB执行下一行,然后暂停。step命令的作用于此类似,只是在函数调用时step命令会进入函数,而next导致程序执行的暂停出现在下次调用函数时。DDD有对应的Next和Step菜单项。

  • 恢复操作

  在GDB中,continue命令通知调试其恢复执行并继续,直到遇到断点为止。DDD中有一个对应的菜单项。

  • 临时断点

  在GDB中,tbreak命令和break相似,但是这一命令设置的断电的有效期只到首次到达指定行时为止。在DDD中临时断点的设置方式为:在源文本窗口中要设置断点的代码行的任意空白处右击,然后选择Set Temporary Breakpoint。

  • GDB中还有创建特殊类型的一次性断点的命令:until和finish。DDD的命令工具中有对应的Until和Finish项。
  • 程序执行的典型调试模式如下(以GDB为例):单击一个断点后,通过GDB的next命令一次移动一行代码,或通过step命令单步调试一段时间,以便仔细检查靠近断点处的程序状态和行为。做完这些操作后,可以用continue命令让调试器继续执行程序,直到遇到下一个断点为止,其间不需要暂停。

GDB的暂停机制

有3种方式可以通知GDB的暂停程序的执行。

断点:通知GDB在程序中的特定位置暂停执行。

监视点:通知GDB当特定内存位置(或者涉及一个或多个位置的表达式)的值发生变化时暂停执行

捕获点:通知GDB当特定事件发生时暂停执行。

断点概述

断点就像程序中的绊网:在程序中的特定“位置”设置断点,当到达那一点时,调试器会暂停程序的执行(在GDB这样的基于文本的调试器的情况下,会出现命令行提示符)。

GDB中关于“位置”的含义是非常灵活的,它可以指各种源代码行、代码地址、源代码文件中的行号或者函数的入口等。

GDB执行到断点行之前,GDB显示的是将要执行的代码行。

然而,GDB的工作针对的是机器语言指令,而不是源代码行,一行代码可能对应于数行机器语言。

可以使用info breakpoints命令获得断点信息。使用delete + 断点编号来删除断点。

设置断点

在GDB中设置断点

GDB中有许多指定断点的方式,下面是一些最常见的方法。

  • break function

  在函数function()的入口(第一行可执行代码)处设置断点。

  (gdb) break main

  在main()的入口处设置断点。

  • break line_number

  在当前活动源代码文件的line_number处设置断点。对于多行程序,这要么是上次使用list命令查看其内容的文件,要么是包含main()的文件。

  (gdb) break 35

  它在文件的第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:parseArguments

  正如我们看到的,当设置一个断点时,该断点的有效性会持续到删除、禁用或退出GDB时。然而,临时断点是首次到达后就会自动删除的断点。临时断点使用tbreak命令设置,它与break采用相同类型的参数。例如,tbreak foo.c在文件的第10行设置临时断点。

  当同一行源代码上有多个断点时会发生什么情况。当GDB使用多个断点中断一行源代码时,它只会中断一次。换言之,当它到达该行代码时,如果恢复执行,会忽略恰好在同一行的其他断点。事实上,GDB知道是哪个断点“触发”了程序停止执行。在具有多个断点的代码行上,触发中断的断点将是标识符编号最小的断点。

 断点的持久性

如果在重新修改编译源代码期间不退出GDB。例如,当发现并修复了一个程序错误,但是其他程序错误仍然存在时,不应当退出GDB然后重新进入来使用程序的新版本。这样做有些不必要地繁琐,而且还会不得不重新进入断点。

如果在修改和重新编译代码时没有退出GDB,那么在下次执行GDB的run命令时,GDB会感知到代码已经修改,并自动重新加载新版本。

删除和禁用断点

如果确认不再需要当前断点,那么可以删除该断点。GDB中有两个用来删除断点的命令。delete命令用来基于标识符删除断点,clear命令使用创建断点相同的语法删除断点。

  • delete breakpoint_list

删除断点使用数值标识符。断点可以是一个数字,比如delete 2删除第二个断点;也可以是数字列表,比如delete 2 4 删除第二个和第四个断点。

  • delete

删除所有断点。除非执行也可以放在.gdbinit启动文件中的set confirm off命令,否则GDB会要求确认删除操作。

  • clear

清除GDB将执行的下一个指令处的断点。这种方法适用于要删除GDB已经到达的断点的情况。

  • clear function、clear filename:function、clear line_number和clear filename:line_number

这些命令根据位置清楚断点,工作方式与对应的break命令相似。

在GDB中禁用断点

每个断点都可以被启用或禁用。只有当GDB遇到启用的断点时,才会暂停程序的执行;它会忽略禁用的断点。默认情况下,断点的生命期从启用时开始。

使用disable breakppoint-list命令禁用断点,使用enable breakpoint-list命令启用断点,其中breakpoint-list是使用空格分隔的列表,其中有一个或多个断点标识符。例如

(gdb) disble 3

将禁用第三个断点。类似地,

(gdb) enable 1 5

将启用第一个和第五个断点。

不带任何参数地执行disable命令将禁用所有现有断点。类似地,不带参数地执行enable命令会启用所有现有断点。

还有一个enable once命令。在断点下次引起GDB暂停执行后被禁用。语法为:

enable once breakpoint-list

 

gdb调试