设置断点是学习使用 GNU 调试器的第一步。程序在达到断点时停止,你可以运行 gdb
的命令对其进行检查或更改变量,然后再允许该程序继续运行。
例如,你可能知道一个经常调用的函数有时会崩溃,但仅当它获得某个参数值时才会崩溃。你可以在该函数的开始处设置一个断点并运行程序。每次碰到该断点时都会显示函数参数,并且如果未提供触发崩溃的参数值,则可以继续操作,直到再次调用该函数为止。当这个惹了麻烦的参数触发崩溃时,你可以单步执行代码以查看问题所在。
-
(gdb) break sometimes_crashes
-
Breakpoint 1 at 0x40110e: file prog.c, line 5.
-
(gdb) run
-
[...]
-
Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
-
5 fprintf(stderr,
-
(gdb) continue
-
Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
-
5 fprintf(stderr,
-
(gdb) continue
为了使此方法更具可重复性,你可以在你感兴趣的特定调用之前计算该函数被调用的次数,并在该断点处设置一个计数器(例如,continue 30
以使其在接下来的 29 次到达该断点时忽略它)。
但是断点真正强大的地方在于它们在运行时评估表达式的能力,这使你可以自动化这种测试。
-
break [LOCATION] if CONDITION
-
(gdb) break sometimes_crashes if !f
-
Breakpoint 1 at 0x401132: file prog.c, line 5.
-
(gdb) run
-
[...]
-
Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:5
-
5 fprintf(stderr,
-
(gdb)
条件断点使你不必让 gdb
每次调用该函数时都去问你要做什么,而是让条件断点仅在特定表达式的值为 true
时才使 gdb
停止在该位置。如果执行到达条件断点的位置,但表达式的计算结果为 false
,调试器会自动使程序继续运行,而无需询问用户该怎么做。
断点命令
GNU 调试器中断点的一个甚至更复杂的功能是能够编写对到达断点的响应的脚本。断点命令使你可以编写一系列 GNU 调试器命令,以在到达该断点时运行。
我们可以使用它来规避在 sometimes_crashes
函数中我们已知的错误,并在它提供空指针时使其无害地从该函数返回。
我们可以使用 silent
作为第一行,以更好地控制输出。否则,每次命中断点时,即使在运行断点命令之前,也会显示堆栈帧。