ℹ️ 本文基于Go Delve 1.4.1
core dump(核心转储)是包含程序内存意外终止快照的文件。它用于事后调试以了解崩溃原因和其中涉及的变量。Go提供了环境变量GOTRACEBACK
用于控制程序崩溃时生成的输出。 此变量还可以强制生成core dump,从而可以进行调试。
GOTRACEBACK
GOTRACEBACK
控制程序崩溃时输出的详细程度。 它可以采用不同的值:
none
不显示任何goroutine栈trace。single
, 默认选项,显示当前goroutine栈trace。all
显示所有用户创建的goroutine栈trace。system
显示所有goroutine栈trace,甚至运行时的trace。crash
类似system
, 而且还会生成 core dump。
最后一个选项使我们能够在发生崩溃的情况下调试程序。 如果没有足够的日志,或者崩溃无法重现,这可能是一个不错的选择。 让我们以以下程序为例:
该程序将很快崩溃:
我们无法从栈trace中分辨出崩溃所涉及的值。增加日志或许是一种解决方案,但是我们并不总是知道在何处添加日志。当问题无法重现时,很难编写测试案例来确保问题被修复。我们可以在添加日志和运行程序之间进行迭代,直到它崩溃并查看到运行后可能的原因。
让我们再次使用GOTRACEBACK=crash
运行它。 由于我们现在已打印出所有goroutine,包括运行时,因此输出更加详细。 并输出core dump:
core dump 是通过 SIGABRT
信号触发。
core dump 可以通过delve或者gdb。
Delve
Delve是使用Go编写的Go程序的调试器。 它可以通过在用户代码以及运行时中的任意位置添加断点来逐步调试,甚至可以使用以二进制文件和core dump为参数的命令 dlv core
调试core dump。
一旦命令运行,我们就可以开始与core dump进行交互了:
dlv
命令bt
打印栈trace并显示程序生成的panic恐慌。 然后,我们可以使用 frame 9
命令访问第9帧:
最后,命令locals
打印局部变量,以帮助了解崩溃所涉及的值:
通道满了, 随机生成的数字为203,300。关于变量 sum
,可以使用打印包变量命令vars
打印:
如果看不到局部变量n的值,请确保使用编译器标志-N
和-l
来构建二进制文件,它会禁用编译器优化,编译器优化可能会使调试更加困难。这是完整的命令:go build -gcflags=all="-N -l"
。 另外,不要忘记运行ulimit -c unlimited
,该选项-c
定义core dump的最大大小。