Go 部落格

Go 程式碼除錯(現狀報告)

Luuk van Dijk
2010 年 11 月 2 日

談到除錯,沒有什麼比一些策略性的列印語句來檢查變數或一個恰當的 panic 來獲取堆疊跟蹤更有效了。然而,有時候你可能缺乏耐心或沒有原始碼,在這些情況下,一個好的偵錯程式是無價的。正因為如此,在過去幾個版本中,我們一直在改進 Go 的 gc 連結器 (6l, 8l) 對 GNU 偵錯程式 GDB 的支援。

在最新的版本 (2010-11-02) 中,6l 和 8l 連結器在生成 ELF (Linux, FreeBSD) 或 Mach-O (Mac OS X) 二進位制檔案時會發出 DWARF3 除錯資訊。DWARF 程式碼足夠豐富,可以實現以下功能:

  • 在 GDB 7.x 版本中載入 Go 程式,
  • 按行顯示所有 Go、C 和彙編原始碼檔案(Go 執行時的一部分是用 C 和彙編編寫的),
  • 按行設定斷點並單步執行程式碼,
  • 列印堆疊跟蹤並檢查堆疊幀,以及
  • 查詢大多數變數的地址並列印其內容。

仍然存在一些不便之處

  • 生成的 DWARF 程式碼無法被 Mac OS X 自帶的 GDB 6.x 版本讀取。我們樂意接受使 DWARF 輸出與標準 OS X GDB 相容的補丁,但在修復之前,您需要在 OS X 下下載、構建和安裝 GDB 7.x 才能使用它。原始碼可以在 http://sourceware.org/gdb/download/ 找到。由於 OS X 的特殊性,您需要在本地檔案系統上使用 chgrp procmodchmod g+s 命令安裝該二進位制檔案。
  • 名稱使用包名進行限定,並且由於 GDB 不理解 Go 包,您必須使用完整的名稱來引用每個項。例如,在 main 包中名為 v 的變數必須引用為 'main.v',並用單引號括起來。由此帶來的一個後果是變數和函式名的 tab 自動補全功能不起作用。
  • 詞法作用域資訊有些模糊。如果存在多個同名變數,第 n 個例項會帶有一個形如 ‘#n’ 的字尾。我們計劃修復這個問題,但這需要對編譯器和連結器之間交換的資料進行一些更改。
  • Slice 和 string 變數在執行時庫中表示為其底層結構。它們看起來像 {data = 0x2aaaaab3e320, len = 1, cap = 1}。對於 slice,您必須解引用資料指標才能檢視其元素。

有些功能尚不起作用

  • Channel、function、interface 和 map 變數無法檢視。
  • 只有 Go 變數標註了型別資訊;執行時的 C 變數沒有。
  • Windows 和 ARM 二進位制檔案不包含 DWARF 除錯資訊,因此無法用 GDB 檢視。

在接下來的幾個月裡,我們打算解決這些問題,無論是透過修改編譯器和連結器,還是透過使用 GDB 的 Python 擴充套件。與此同時,我們希望 Go 程式設計師能從更好地使用這個知名的除錯工具中受益。

附註:DWARF 資訊也可以被 GDB 以外的工具讀取。例如,在 Linux 上,您可以將其與 sysprof 系統級分析器一起使用。

下一篇文章:Go:一年前的今天
上一篇文章:Go 實際專案:SmartTwitter 和 web.go
部落格目錄