Go:使用 Delve 和 Core Dump 調(diào)試代碼

?? 這篇文章基于 Go Delve 1.4.1。
core dump 是一個(gè)包含著意外終止的程序其內(nèi)存快照的文件。這個(gè)文件可以被用來事后調(diào)試(debugging)以了解為什么會(huì)發(fā)生崩潰,同時(shí)了解其中涉及到的變量。通過 GOTRACEBACK,Go 提供了一個(gè)環(huán)境變量用于控制程序崩潰時(shí)生成的輸出信息。這個(gè)變量同樣可以強(qiáng)制生成 core dump,從而使調(diào)試成為可能。
GOTRACEBACK
GOTRACEBACK 控制著當(dāng)程序崩潰時(shí)輸入的詳細(xì)程度。它可以使用不同的值:
none不顯示任何 Goroutine 的堆棧信息。single,默認(rèn)選項(xiàng),顯示當(dāng)前 Goroutine 的堆棧信息。all顯示所有用戶創(chuàng)建的 Goroutine 的堆棧信息。system顯示所有 Goroutine 的堆棧信息,即使是來自運(yùn)行時(shí)的 goroutine。crash與system類似,但是會(huì)生成 core dump。
最后的那個(gè)選項(xiàng),給了我們?cè)诔绦虮罎⒌那闆r下,調(diào)試我們程序的能力。如果沒有足夠的日志,或者崩潰無法復(fù)現(xiàn)時(shí),這是一個(gè)好的選擇。讓我們以下面的程序?yàn)槔?/p>

這個(gè)程序會(huì)很快崩潰:

從堆棧信息中我們無法獲知那個(gè)值涉及了程序的崩潰。增加日志是一個(gè)解決辦法,但我們無法一直知道要在哪里加日志。當(dāng)問題無法復(fù)現(xiàn)的時(shí)候,編寫測(cè)試用例以確保問題被修復(fù)是十分困難的。我們可以不斷重復(fù)增加日志和運(yùn)行程序的步驟,直到程序崩潰,再查看可能的原因后再運(yùn)行。
設(shè)置 GOTRACEBACK=crash 后再次運(yùn)行。輸出信息更加詳細(xì),因?yàn)楝F(xiàn)在所有的 Goroutine 信息打印了出來,包括運(yùn)行時(shí)的。無論如何,我們現(xiàn)在有了 core dump。

core dump 通過 SIGABRT 信號(hào)觸發(fā),該信號(hào)生成 core dump 作為處置[1]。
core dump 可以被諸如 Go delve[2] 或者 GBD[3] 的調(diào)試信息分析。
Delve
Delve 是用 Go 語(yǔ)言編寫的 Go 程序調(diào)試器。它允許通過在用戶代碼和運(yùn)行時(shí)代碼的任意位置加斷點(diǎn)來逐步調(diào)試,甚至通過 dlv core 命令來調(diào)試 core dump,這個(gè)命令以二進(jìn)制和 core dump 為參數(shù)。
一旦命令運(yùn)行,我們就可以開始與 core dump 進(jìn)行交互:

dlv 命令 bt 打印堆棧信息并且顯示程序生成的 panic 信息。之后,我們可以通過 frame 9 命令來訪問 9 號(hào)幀:

最終,用 locals 命令打印本地變量,來幫助了解哪個(gè)變量與崩潰有關(guān):

channel 是滿的,并且生成的隨機(jī)數(shù)是 203,300。而對(duì)于變量 sum,可以通過命令 vars 打印出它的內(nèi)容,該命令用于打印包級(jí)別變量:

如果沒有看到本地變量 n ,請(qǐng)確保使用編輯標(biāo)志 -N 和 -l 來構(gòu)建二進(jìn)制程序,這些標(biāo)志禁用編譯器優(yōu)化,而這些優(yōu)化會(huì)是調(diào)試更加困難。完整的編譯命令是:go build -gcflags=all="-N -l" 不要忘記運(yùn)行 ulimit -c unlimited,選項(xiàng) -c 定義了 core dump 的最大尺寸。
via: https://medium.com/a-journey-with-go/go-debugging-with-delve-core-dumps-384145b2e8d9
作者:Vincent Blanchon[4]譯者:dust347[5]校對(duì):polaris1119[6]
本文由 GCTT[7] 原創(chuàng)編譯,Go 中文網(wǎng)[8] 榮譽(yù)推出
參考資料
生成 core dump 作為處置: http://man7.org/linux/man-pages/man7/signal.7.html
[2]Go delve: https://github.com/go-delve/delve
[3]GBD: https://www.gnu.org/s/gdb/
[4]Vincent Blanchon: https://medium.com/@blanchon.vincent
[5]dust347: https://github.com/dust347
[6]polaris1119: https://github.com/polaris1119
[7]GCTT: https://github.com/studygolang/GCTT
[8]Go 中文網(wǎng): https://studygolang.com/
推薦閱讀
xxx
