因为我们需要调试的是变量 y。我们可以在y被设置的地方放置断点然后单步执行。可以使用 info args 查看函数的参数,在 bt 之前可以返回当前回溯。
(gdb) b 'main.f'
(gdb) run
Starting program: /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/gdb_sandbox
Breakpoint 1, main.f (x=0, ~anon1=833492132160)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x*x + x
(gdb) info args
x = 0
(gdb) continue
Breakpoint 1, main.f (x=0, ~anon1=833492132160)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x*x + x
(gdb) info args
x = 2
(gdb) bt
#0 main.f (x=2, ~anon1=1)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
#1 0x0000000000400f0e in main.handleNumber (i=2, ~anon1=0x1)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:24
#2 0x0000000000400c47 in main.main ()
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:14
因为我们在变量 y 是在函数 f 中被设定的这样一个条件下,我们可以跳到这个函数的上下文并检查堆区的代码。应用运行时我们可以在一个更高的层次上设置断点并检查其状态。
(gdb) b main.go:26
Breakpoint 2 at 0x400f22: file
/home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go, line 26.
(gdb) continue
Continuing.
Breakpoint 2, main.handleNumber (i=2, ~anon1=0x1)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:28
28 y: val,
(gdb) l
23 if i%2 == 0 {
24 val = f(i)
25 }
26 return &pair{
27 x: i,
28 y: val,
29 }
30 }
31
32 func f(x int) int {
(gdb) p val
$1 = 6
(gdb) p i
$2 = 2
如果我们在这个断点处继续住下走我们将越过在这个函数中的断点1,而且将立即触发在 HandleNumer 函数中的断点,因为函数 f 只是对变量 i 每隔一次才执行。我们可以通过暂时使断点 2不工作来避免这种情况的发生。
(gdb) disable breakpoint 2
(gdb) continue
Continuing.
&{x:2 y:6}
looping
&{x:3 y:3}
looping
[New LWP 15200]
[Switching to LWP 15200]
Breakpoint 1, main.f (x=4, ~anon1=1)
at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x*x + x
(gdb)
我们也可以分别使用 clear 和 delete breakpoint NUMBER 来清除和删除断点。动态产生和系住断点,我们可以有效地在应用流中来回移动。
Slices and Pointers