天天看点

gdb调试

调试工具:

gdb

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

ddd

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

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

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

主要调试器操作

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

继续阅读