Go 部落格
除錯 Go 程式碼(狀態報告)
說到除錯,沒有什麼比幾個有策略的列印語句來檢查變數或一個恰到好處的 panic 來獲取堆疊跟蹤更有效了。然而,有時你可能缺乏耐心或原始碼,在這些情況下,一個好的偵錯程式將非常寶貴。這就是為什麼在過去的幾個版本中,我們一直在改進 Go 的 gc 連結器(6l, 8l)對 GDB(GNU 偵錯程式)的支援。
在最新版本(2010-11-02)中,6l 和 8l 連結器在編寫 ELF(Linux, FreeBSD)或 Mach-O(Mac OS X)二進位制檔案時會發出 DWARF3 除錯資訊。DWARF 程式碼足夠豐富,可以讓你做到以下幾點:
- 在 GDB 7.x 版本中載入 Go 程式,
- 按行列表出所有 Go、C 和彙編原始碼檔案(Go 執行時的一部分是用 C 和彙編編寫的),
- 按行設定斷點並單步執行程式碼,
- 列印堆疊跟蹤並檢查堆疊幀,以及
- 查詢地址並列印大多數變數的內容。
仍然存在一些不便之處
- Mac OS X 自帶的 GDB 6.x 版本無法讀取發出的 DWARF 程式碼。我們非常樂意接受補丁,使 DWARF 輸出與標準的 OS X GDB 相容,但在此修復之前,你需要下載、構建並安裝 GDB 7.x 才能在 OS X 下使用它。原始碼可以在 http://sourceware.org/gdb/download/ 找到。由於 OS X 的特殊性,你需要在本地檔案系統上安裝該二進位制檔案,並執行
chgrp procmod
和chmod g+s
命令。 - 名稱會帶有包名進行限定,由於 GDB 不理解 Go 包,因此你必須使用其完整名稱來引用每個項。例如,在
main
包中名為v
的變數必須引用為'main.v'
,用單引號括起來。其後果是變數和函式名的製表符自動補全不起作用。 - 詞法作用域資訊有些模糊。如果存在同名的多個變數,則第 n 個例項將帶有後綴 ‘#n’。我們計劃修復此問題,但這需要對編譯器和連結器之間交換的資料進行一些更改。
- 切片和字串變數以其在執行時庫中的底層結構表示。它們看起來會像
{data = 0x2aaaaab3e320, len = 1, cap = 1}
。對於切片,你必須解引用資料指標才能檢查元素。
有些功能尚不可用
- 無法檢查通道、函式、介面和對映變數。
- 只有 Go 變數帶有型別資訊註解;執行時中的 C 變數則沒有。
- Windows 和 ARM 二進位制檔案不包含 DWARF 除錯資訊,因此無法使用 GDB 進行檢查。
在接下來的幾個月裡,我們打算透過更改編譯器和連結器或使用 GDB 的 Python 擴充套件來解決這些問題。在此期間,我們希望 Go 程式設計師能從獲得對這個著名除錯工具的更好訪問許可權中受益。
附註:除 GDB 外,其他工具也可以讀取 DWARF 資訊。例如,在 Linux 上,你可以將其與 sysprof 系統範圍的效能分析器一起使用。
下一篇文章:Go:一年前的今天
上一篇文章:真實的 Go 專案:SmartTwitter 和 web.go
部落格索引