【Go】Go语言的调试利器 dlv debug
目录
简述
之前介绍了Go如何产生coredump,也发现了gdb无法分析Go生成的coredump文件,今天来一起学习一下,Go语言的调试利器 dlv 如何分析coredump。
开始
环境安装
Linux环境安装:
方法一:
go get github.com/go-delve/delve/cmd/dlv
注意:如果在go mod
的模式下使用 Go,则必须在模块目录之外执行此命令,否则 Delve 将作为依赖项添加到项目中。
方法二:
确保$GOPATH设置:
|
|
- 推荐使用第一种的方法。
分析coredump
- Demo
|
|
gdb查看,发现查不出什么问题来。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
$ gdb main core.main.4744 GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /root/main/main...done. [New LWP 4744] [New LWP 4748] [New LWP 4746] [New LWP 4745] [New LWP 4747] Core was generated by `./main'. Program terminated with signal 6, Aborted. #0 runtime.raise () at /usr/local/go/src/runtime/sys_linux_amd64.s:165 165 RET warning: File "/usr/local/go/src/runtime/runtime-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/usr/bin/mono-gdb.py". To enable execution of this file add add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py line to your configuration file "/root/.gdbinit". To completely disable this security protection add set auto-load safe-path / line to your configuration file "/root/.gdbinit". For more information about this security protection see the "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: info "(gdb)Auto-loading safe path" (gdb) bt full #0 runtime.raise () at /usr/local/go/src/runtime/sys_linux_amd64.s:165 No locals. #1 0x000000000044637d in runtime.dieFromSignal (sig=6) at /usr/local/go/src/runtime/signal_unix.go:776 No locals. #2 0x0000000000446891 in runtime.sigfwdgo (sig=6, info=0xc000009bf0, ctx=0xc000009ac0, ~r3=<optimized out>) at /usr/local/go/src/runtime/signal_unix.go:990 fwdFn = <optimized out> flags = <optimized out> g = <optimized out> #3 0x0000000000445034 in runtime.sigtrampgo (sig=6, info=0xc000009bf0, ctx=0xc000009ac0) at /usr/local/go/src/runtime/signal_unix.go:428 setStack = <optimized out> gsignalStack = <optimized out> g = <optimized out> #4 0x0000000000464da3 in runtime.sigtramp () at /usr/local/go/src/runtime/sys_linux_amd64.s:409 No locals. #5 0x0000000000464ea0 in ?? () No locals. #6 0x0000000000000007 in ?? () No symbol table info available. #7 0x0000000000000000 in ?? () ---Type <return> to continue, or q <return> to quit--- No symbol table info available.
使用dlv分析
1 2 3 4
// dlv core {运行文件} {coredump文件} $ dlv core main core.main.4744 Type 'help' for list of commands. (dlv)
查看所有的goroutines
1 2 3 4 5 6 7
(dlv) goroutines * Goroutine 1 - User: ./main.go:8 main.main (0x49915a) (thread 4744) Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:307 runtime.gopark (0x434e85) Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:307 runtime.gopark (0x434e85) Goroutine 4 - User: /usr/local/go/src/runtime/proc.go:307 runtime.gopark (0x434e85) Goroutine 17 - User: /usr/local/go/src/runtime/mfinal.go:161 runtime.runfinq (0x416340) [5 goroutines]
选择异常的goroutines并查看
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 27 28 29 30
(dlv) goroutine 1 Switched from 1 to 1 (thread 4744) (dlv) bt 0 0x0000000000464a01 in runtime.raise at /usr/local/go/src/runtime/sys_linux_amd64.s:165 1 0x000000000044637d in runtime.dieFromSignal at /usr/local/go/src/runtime/signal_unix.go:776 2 0x0000000000446891 in runtime.sigfwdgo at /usr/local/go/src/runtime/signal_unix.go:990 3 0x0000000000445034 in runtime.sigtrampgo at /usr/local/go/src/runtime/signal_unix.go:428 4 0x0000000000464da3 in runtime.sigtramp at /usr/local/go/src/runtime/sys_linux_amd64.s:409 5 0x0000000000464ea0 in runtime.sigreturn at /usr/local/go/src/runtime/sys_linux_amd64.s:501 6 0x000000000043254b in runtime.crash at /usr/local/go/src/runtime/signal_unix.go:868 7 0x000000000043254b in runtime.fatalpanic at /usr/local/go/src/runtime/panic.go:1216 8 0x0000000000431e85 in runtime.gopanic at /usr/local/go/src/runtime/panic.go:1064 9 0x000000000043059b in runtime.panicdivide at /usr/local/go/src/runtime/panic.go:191 10 0x000000000049915a in main.main at ./main.go:8 11 0x0000000000434a89 in runtime.main at /usr/local/go/src/runtime/proc.go:204 12 0x0000000000463201 in runtime.goexit at /usr/local/go/src/runtime/asm_amd64.s:1374 (dlv)
查看代码出现问题的地方
1 2 3 4 5 6 7 8 9 10 11 12
(dlv) frame 10 > runtime.raise() /usr/local/go/src/runtime/sys_linux_amd64.s:165 (PC: 0x464a01) Warning: debugging optimized function Frame 10: ./main.go:8 (PC: 49915a) 3: import "fmt" 4: 5: func main() { 6: a := 10 7: for i := 1; i <= 10; i++ { => 8: fmt.Println(a/(10-i)) 9: } 10: }
测试完成,基本定位到出问题代码的位置。
总结
dlv不仅仅只是可以分析coredump这边简单的功能,还有非常强大的使用方式,时间原因,先简单的写,后续扩展怎么使用dlv调试。