Go語言debug調試

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

原文:GDB調試Go程式

說明:作為一門靜態語言,似乎支援調試是必須的,而且,Go初學者喜歡問的問題也是:大家都用什麼IDE?怎麼調試?

其實,Go是為多核和並發而生,真正的項目,你用單步調試,原本沒問題的,可能會調出有問題。更好的調試方式是跟PHP這種語言一樣,用列印的方式(日誌或print)。

當然,簡單的小程式,如果單步調試,可以看到一些內部的運行機理,對於學習還是挺有好處的。下面介紹一下用GDB調試Go程式:(目前IDE支援調試Go程式,用的也是GDB。要求GDB 7.1以上)

以下內容來自雨痕的《Go語言學習筆記》(下載Go資源):

預設情況下,編譯過的二進位檔案已經包含了 DWARFv3 調試資訊,只要 GDB7.1 以上版本都可以進行調試。 在OSX下,如無法執行調試指令,可嘗試用sudo方式執行gdb。

刪除偵錯符號:go build -ldflags “-s -w”

  • -s: 去掉符號資訊。
  • -w: 去掉DWARF調試資訊。

關閉內聯最佳化:go build -gcflags “-N -l”

調試相關函數:

  • runtime.Breakpoint():觸發調試器斷點。
  • runtime/debug.PrintStack():顯示調試堆棧。
  • log:適合替代 print顯示調試資訊。

GDB 調試支援:

  • 參數載入:gdb -d $GCROOT 。
  • 手工載入:source pkg/runtime/runtime-gdb.py。

更多細節,請參考: http://golang.org/doc/gdb

調試示範:(OSX 10.8.2, Go1.0.3, GDB7.5.1)

1 package main
2  
3 import (
4     "fmt"
5     "runtime"
6 )
7  
8 func test(s string, x int) (r string) {
9     r = fmt.Sprintf("test: %s %d", s, x)
10     runtime.Breakpoint()
11     return r
12 }
13 func main() {
14     s := "haha"
15     i := 1234
16     println(test(s, i))
17 }

$ go build -gcflags “-N -l” // 編譯,關閉內聯最佳化。

$ sudo gdb demo // 啟動 gdb 調試器,手工載入 Go Runtime 。
GNU gdb (GDB) 7.5.1
Reading symbols from demo…done.
(gdb) source /usr/local/go/src/pkg/runtime/runtime-gdb.py
Loading Go Runtime support.

(gdb) l main.main // 以 .方式查看源碼。
9 r = fmt.Sprintf(“test: %s %d”, s, x)
10 runtime.Breakpoint()
11 return r
12 }
13
14 func main() {
15 s := “haha”
16 i := 1234
17 println(test(s, i))
18 }

(gdb) l main.go:8 // 以 :方式查看源碼。
3 import (
4 “fmt”
5 “runtime”
6 )
7
8 func test(s string, x int) (r string) {
9 r = fmt.Sprintf(“test: %s %d”, s, x)
10 runtime.Breakpoint()
11 return r
12 }

(gdb) b main.main // 以 .方式設定斷點。
Breakpoint 1 at 0×2131: file main.go, line 14.

(gdb) b main.go:17 // 以 :方式設定斷點。
Breakpoint 2 at 0×2167: file main.go, line 17.

(gdb) info breakpoints // 查看所有斷點。
Num Type Disp Enb Address What
1 breakpoint keep y 0×0000000000002131 in main.main at main.go:14
2 breakpoint keep y 0×0000000000002167 in main.main at main.go:17

(gdb) r // 啟動進程,觸發第一個斷點。
Starting program: demo
[New Thread 0x1c03 of process 4088]
[Switching to Thread 0x1c03 of process 4088]
Breakpoint 1, main.main () at main.go:14
14 func main() {

(gdb) info goroutines // 查看 goroutines 資訊。
* 1 running runtime.gosched
* 2 syscall runtime.entersyscall

(gdb) goroutine 1 bt // 查看指定序號的 goroutine 呼叫堆疊。
#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927
#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244
#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267
#3 0×0000000000000000 in ?? ()

(gdb) goroutine 2 bt // 這個 goroutine 貌似跟 GC 有關。
#0 runtime.entersyscall () at pkg/runtime/proc.c:989
#1 0x000000000000d01d in runtime.MHeap_Scavenger () at pkg/runtime/mheap.c:363
#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267
#3 0×0000000000000000 in ?? ()

(gdb) c / / 繼續執行,觸發下一個斷點。
Continuing.
Breakpoint 2, main.main () at main.go:17
17! ! println(test(s, i))

(gdb) info goroutines // 當前 goroutine 序號為 1。
* 1 running runtime.gosched
2 runnable runtime.gosched

(gdb) goroutine 1 bt // 當前 goroutine 呼叫堆疊。
#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927
#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244
#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267
#3 0×0000000000000000 in ?? ()

(gdb) bt // 查看當前調⽤堆棧,可以與當前 goroutine 呼叫堆疊對比。
#0 main.main () at main.go:17
#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244
#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267
#3 0×0000000000000000 in ?? ()

(gdb) info frame // 堆疊框架資訊。
Stack level 0, frame at 0x442139f88:
rip = 0×2167 in main.main (main.go:17); saved rip 0xe44c
called by frame at 0x442139fb8
source language go.
Arglist at 0x442139f28, args:
Locals at 0x442139f28, Previous frame’s sp is 0x442139f88
Saved registers:
rip at 0x442139f80

(gdb) info locals // 查看局部變數。
i = 1234
s = “haha”

(gdb) p s // 以 Pretty-Print 方式查看變數。
$1 = “haha”

(gdb) p $len(s) // 擷取對象長度($cap)
$2 = 4

(gdb) whatis i // 查看物件類型。
type = int

(gdb) c // 繼續執行,觸發 breakpoint() 斷點。
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
runtime.breakpoint () at pkg/runtime/asm_amd64.s:81
81 RET

(gdb) n // 從 breakpoint() 中出來,執行源碼下一行代碼。
main.test (s=”haha”, x=1234, r=”test: haha 1234″) at main.go:11
11 return r

(gdb) info args // 從參數資訊中,我們可以看到命名返回參數的值。
s = “haha”
x = 1234
r = “test: haha 1234″

(gdb) x/3xw &r // 查看 r 記憶體資料。(指標 8 + 長度 4)
0x442139f48: 0×42121240 0×00000000 0x0000000f
(gdb) x/15xb 0×42121240 // 查看字串位元組數組
0×42121240: 0×74 0×65 0×73 0×74 0x3a 0×20 0×68 0×61
0×42121248: 0×68 0×61 0×20 0×31 0×32 0×33 0×34

(gdb) c // 繼續執行,進程結束。

Continuing.
test: haha 1234
[Inferior 1 (process 4088) exited normally]

(gdb) q // 退出 GDB。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.