GoLand编辑器虽然很强大,但是在展示内存及堆栈信息这一块还是比较的弱,有可能是我的姿势不对,所以,开始切入了gdb调试,但是gdb踩到了坑,并没有解决,也就引发了gdb与dlv的对比了
gdb
安装
1 | yum install ncures-devel |
进入调试
1 | go build -gcflags '-N -l' main.go |
使用
启动调试程序(
gdb
)1
[lday@alex GoDbg]$ gdb ./GoDbg
在main函数上设置断点(
b
)1
2(gdb) b main.main
Breakpoint 1 at 0x401000: file /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go, line 9.带参数启动程序(
r
)1
2
3
4
5
6
7
8
9(gdb) r arg1 arg2
Starting program: /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/GoDbg arg1 arg2
[New LWP 8412]
[New LWP 8413]
[New LWP 8414]
[New LWP 8415]
Breakpoint 1, main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
9 func main() {在文件dbgTest.go上通过行号设置断点(
b
)1
2(gdb) b dbgTest.go:16
Breakpoint 3 at 0x457960: file /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go, line 16.查看断点设置情况(
info b
)1
2
3
4
5
6
7
8
9
10(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000401000 in main.main
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
breakpoint already hit 1 time
2 breakpoint keep y 0x0000000000401000 in main.main
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
breakpoint already hit 1 time
3 breakpoint keep y 0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16禁用断点(
dis n
)1
2
3
4
5
6
7
8
9
10
11(gdb) dis 1
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep n 0x0000000000401000 in main.main
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
breakpoint already hit 1 time
2 breakpoint keep y 0x0000000000401000 in main.main
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
breakpoint already hit 1 time
3 breakpoint keep y 0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16删除断点(
del n
)1
2
3
4
5
6
7
8(gdb) del 1
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x0000000000401000 in main.main
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:9
breakpoint already hit 1 time
3 breakpoint keep y 0x0000000000457960 in GoWorks/GoDbg/mylib.DBGTestRun
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16断点后继续执行(
c
)1
2
3
4
5
6
7
8
9
10(gdb) c
Continuing.
Golang dbg test...
argc:3
argv:[/home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/GoDbg arg1 arg2]
Breakpoint 3, GoWorks/GoDbg/mylib.DBGTestRun (var1=1, var2="golang dbg test")
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:16
16 func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
(gdb)显示代码(
l
)1
2
3
4
5
6
7
8
9
10
11(gdb) l
11 B string
12 C map[int]string
13 D []string
14 }
15
16 func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
17 fmt.Println("DBGTestRun Begin!\n")
18 waiter := &sync.WaitGroup{}
19
20 waiter.Add(1)单步执行(
n
)1
2
3
4(gdb) n
DBGTestRun Begin!
18 waiter := &sync.WaitGroup{}打印变量信息(
print/p
)
在进入DBGTestRun的地方设置断点(b dbgTest.go:16
),进入该函数后,通过p命令显示对应变量:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17(gdb) l 17
12 C map[int]string
13 D []string
14 }
15
16 func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
17 fmt.Println("DBGTestRun Begin!\n")
18 waiter := &sync.WaitGroup{}
19
20 waiter.Add(1)
21 go RunFunc1(var1, waiter)
(gdb) p var1
$3 = 1
(gdb) p var2
$4 = "golang dbg test"
(gdb) p var3
No symbol "var3" in current context.从上面的输出我们可以看到一个很奇怪的事情,虽然DBGTestRun有4个参数传入,但是,似乎var3和var4 gdb无法识别,在后续对dlv的实验操作中,我们发现,dlv能够识别var3, var4.
查看调用栈(
bt
),切换调用栈(f n
),显示当前栈变量信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26(gdb) bt
#0 GoWorks/GoDbg/mylib.DBGTestRun (var1=1, var2="golang dbg test")
at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/mylib/dbgTest.go:17
#1 0x00000000004018c2 in main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:27
(gdb) f 1
#1 0x00000000004018c2 in main.main () at /home/lday/Works/Go_Works/GoLocalWorks/src/GoWorks/GoDbg/main.go:27
27 mylib.DBGTestRun(var1, var2, var3, var4)
(gdb) l
22 var4.A = 1
23 var4.B = "golang dbg my struct field B"
24 var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
25 var4.D = []string{"D1", "D2", "D3"}
26
27 mylib.DBGTestRun(var1, var2, var3, var4)
28 fmt.Println("Golang dbg test over")
29 }
(gdb) print var1
$5 = 1
(gdb) print var2
$6 = "golang dbg test"
(gdb) print var3
$7 = []int = {1, 2, 3}
(gdb) print var4
$8 = {A = 1, B = "golang dbg my struct field B", C = map[int]string = {[1] = "value1", [2] = "value2", [3] = "value3"},
D = []string = {"D1", "D2", "D3"}}
dlv(推荐)
安装
1 | go get -u github.com/go-delve/delve/cmd/dlv |
进入调试
1 | dlv debug main.go |
使用
1 | args ------------------------ Print function arguments. |
总结
dlv对goroutine的支持更好,我使用gdb的没有找到goroutine的调试方法,可能姿势不对
gdb对于局部引用变量无法调试,dlv不会
1
2
3
4func main() {
i := 10
j := &i
}如上代码,gdb 使用
p j
打印变量j的时候报错,dlv却可以dlv无法调试interface等Go内部实现的一些结构,gdb是可以的