go程式調試總結

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

首先需要注意的是:golang1.3之後的版本,對於支援gdb調試存在很大的問題。產生這個問題的原因是,golang的runtime沒有完整的被gdb支援。

最新比較完整支援gdb調試的版本是golang 1.2.2,但是也有個別問題存在。

為什麼會出現以上種種問題,golang官網給出的解釋是:

GDB does not understand Go programs well. The stack management, threading, and runtime contain aspects that differ enough from the execution model GDB expects that they can confuse the debugger, even when the program is compiled with gccgo. As a consequence, although GDB can be useful in some situations, it is not a reliable debugger for Go programs, particularly heavily concurrent ones. Moreover, it is not a priority for the Go project to address these issues, which are difficult. In short, the instructions below should be taken only as a guide to how to use GDB when it works, not as a guarantee of success.

翻譯一下:

GDB不能很好的理解GO程式。堆棧管理、線程和runtime包含了非常不一樣的執行模式,這不是GDB期望的,他們會擾亂調試器,即使go程式是使用gccgo編譯的。結果就是,雖然GDB在某些場合下是有用的,但是對go程式來說並不是一個可靠的調試器。尤其是在大量並發的時候。而且,這不是Golang項目優先考慮的事情,這很困難。總而言之,下面的操作手冊,只是當GDB正常工作的時候,引導你如何使用GDB,不能保證總是成功。

並且從google group討論群組和stackoverflow中,可以看到golang的多個版本對於GDB的支援都有這樣那樣的問題。不過既然官方的手冊都這麼說了,我們也只有在合適的場合使用GDB吧。

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

在編譯go程式的時候,需要關閉內聯最佳化:** -gcflags “-N -l”**。可以在go get/build/test的時候指定這個參數。

有兩種方式可以下斷點:

  • gdb命令運行之後,使用break file:lineno
  • 使用runtime.BreakPoint()

示範環境:Ubuntu 14.04 LTS amd64 / Golang 1.2.2 / GDB 7.7

package mainimport (    "fmt"    "runtime")func test(s string, x int) (r string) {    r = fmt.Sprintf("test: %s %d", s, x)    runtime.Breakpoint()    return r}func main() {    s := "haha"    i := 1234    println(test(s, i))}

啟動GDB:

➜  ~  gdb ./testGNU gdb (Ubuntu 7.7-0ubuntu3) 7.7Copyright (C) 2014 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:.Find the GDB manual and other documentation resources online at:.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from ./test...done.**Loading Go Runtime support.**(gdb)

以模組名的方式查看源碼:

(gdb) l main.main9       r = fmt.Sprintf("test: %s %d", s, x)10      runtime.Breakpoint()11      return r12  }1314  func main() {15      s := "haha"16      i := 123417      println(test(s, i))

以檔案名稱加行號的方式查看源碼:

(gdb) l /home/roy/test.go:11   package main23   import (4       "fmt"5       "runtime"6   )78   func test(s string, x int) (r string) {9       r = fmt.Sprintf("test: %s %d", s, x)10      runtime.Breakpoint()

設定斷點:

(gdb) b main.mainBreakpoint 2 at 0x400d80: file /home/roy/test.go, line 14.(gdb) b test.go:18Breakpoint 3 at 0x400e0e: file /home/roy/test.go, line 18.

啟動進程,觸發斷點:(n 逐步執行,c執行到下一個斷點)

(gdb) runStarting program: /home/roy/testBreakpoint 2, main.main () at /home/roy/test.go:1414  func main() {

查看goroutines:

(gdb) info goroutines* 1  running runtime.gosched* 2  syscall runtime.notetsleepg

查看指定goroutine的呼叫堆疊:

(gdb) goroutine 1 btPython Exception  Cannot access memory at address 0x8:Error occurred in Python command: Cannot access memory at address 0x8

當我們想查看goroutine呼叫堆疊的時候,gdb報告無法訪問記憶體。Cannot access memory at address 0x8,這句是說無法訪問0x8位置的記憶體,所以接下來,gdb收到了一個SIGSEGV的訊號,說明觸發了段錯誤:

(gdb) nProgram received signal SIGSEGV, Segmentation fault.0x000000000041529b in runtime.gosched () at /home/roy/go/src/pkg/runtime/proc.c:13681368        runtime·mcall(runtime·gosched0);

此時,我們需要重啟gdb的調試,否則執行任何命令都會報告段錯誤。

列印棧幀資訊:

(gdb) info frameStack level 0, frame at 0x7ffff7e2ef48: rip = 0x400d80 in main.main (/home/roy/test.go:14); saved rip = 0x412e1f source language go. Arglist at 0x7ffff7e2ef38, args: Locals at 0x7ffff7e2ef38, Previous frame's sp is 0x7ffff7e2ef48 Saved registers: rip at 0x7ffff7e2ef40

查看局部變數:

(gdb) info localsi = 1234s = "haha"

以Pretty-Print的方式列印變數:

(gdb) p s$1 = "haha"

擷取對象的長度,即cap:

(gdb) p $len(s)$3 = 4

查看物件類型:

(gdb) whatis itype = int(gdb) whatis stype = struct string

輸入n逐步執行到進入test函數,查看傳遞給函數的參數:

(gdb) nmain.test (s="haha", x=1234, r="test: haha 1234") at /home/roy/test.go:1111      return r(gdb) info argss = "haha"x = 1234r = "test: haha 1234"

輸入q,或者Ctrl-D退出:

(gdb) qA debugging session is active.    Inferior 1 [process 6079] will be killed.Quit anyway? (y or n) y

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.