Slide 1

Slide 1 text

gdb で Go デバッグ 黒川 洋 / @hydrakecat

Slide 2

Slide 2 text

Go のデバッグ、してますか? Go のデバッグについて、周囲の Go エンジニアに聞いてみました。 printデバッグで十分 Go のコードは、見れば分かる! そもそもエンバグしないので必要ないぜ!! 人人人人人人人人人人人人人人人人人_ > だれもデバッガを使っていない! <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

Slide 3

Slide 3 text

print デバッグ vs. デバッガ print デバッグ 準備が不要 出力を変えるためにコンパイ ルが必要 処理を途中で止められない デバッガの問題で消耗しない デバッガ 準備が大変 すべての変数を参照可能 処理を途中で止められる 実行中のプロセスにアタッチで きる マルチスレッドの問題を解析し やすい <= 重要!

Slide 4

Slide 4 text

go のデバッガ ほぼ gdb 一択: gdb 向けに、いくつか拡張がされている string, slice, map, channel 用に最適化された出力 slice と map 用のコマンド$len()と$cap()がある interface 型の変数を動的型にキャストする$dtype()とiface がある goroutine 用のコマンドがある Debugging Go Code with GDB (gdb) p urls $11 = []string = {"http://golang.org/", "http://golang.org/cmd"} (gdb) whtais var type = main.MyInterface (gdb) p $dtype(var) $26 = (struct struct MyImpl) 0xf8400b4930 (gdb) iface var main.MyInterface: struct MyImpl (gdb) info goroutines (gdb) goroutine cmd

Slide 5

Slide 5 text

使い方 1. オプション付きでビルドする 2. gdb を起動する 3. ブレークポイントをセットする 4. プログラムを実行する 5. 変数を見たり、ステップ実行したりする go build ­gcflags "­N ­l" main.go gdb main (gdb) break main.go:17 (gdb) run Starting program: /home/hiroshi/go/src/github.com/hkurokawa/go­dbg­sample/main Breakpoint 1, main.function_01 (˜r0=0xc208000150) at /home/hiroshi/go/src/github.com/hkurokawa/go­dbg­sa 17 return h (gdb)

Slide 6

Slide 6 text

基本的なコマンド (1/3) list (l) 周りのソースコードを表示する break (b) ブレークポイントをセットする 行番号 メソッド名 <パッケージ名>.(<レシーバー名>.)<メソッド名>になるので注意! next (n), step (s) ステップ実行をする <何も入力しないで Enter> 直前に実行したコマンドを実行する (gdb) l 93 machine []*machine 94 } 95 96 // String returns the source text used to compile the regular expression. 97 func (re *Regexp) String() string { (gdb) break main.go:17 (gdb) b main.Crawl (gdb) b main.(*fakeFetcher).Crawl

Slide 7

Slide 7 text

基本的なコマンド (2/3) continue (c) 実行を再開する print (p) 変数の中身を表示する ポインタ型に対しては*や­>を使って参照先を表示できる グローバル変数は<パッケージ名>.<変数名>でアクセスする。 info variables <正規表現>で目的の変数を探して表示すると良い。 backtrace (bt) スタックトレースを表示する (gdb) p t $1 = (struct testing.T *) 0xf840688b60 (gdb) p *t $2 = {errors = "", failed = false, ch = 0xf8406f5690} (gdb) p *t­>ch $3 = struct hchan<*testing.T> (gdb) info variables config All variables matching regular expression "config": struct github.com/hkurokawa/go­sandbox/go­gdb­sample.ConfigStruct *github.com/hkurokawa/go­sandbox/g (gdb) p 'github.com/hkurokawa/go­sandbox/go­gdb­sample.config'

Slide 8

Slide 8 text

基本的なコマンド (3/3) info (i) 様々な情報を表示する info args 引数を表示する info locals/variables ローカル/グローバル変数をすべて表示 info goroutines 現在の goroutine の情報を表示する。*が付い ているのが、現在のスレッド。 goroutine 指定 goroutine でコマンド実行 iface インタフェース型変数の動的な型を表示する。はずだが? (gdb) info goroutines 1 waiting runtime.park 2 runnable runtime.exitsyscall * 4 running main.Crawl 5 runnable main.Crawl (gdb) goroutine 5 bt (gdb) whatis fetcher type = main.Fetcher (gdb) iface fetcher Not an interface: main.Fetcher

Slide 9

Slide 9 text

注意点 Windows では使えません GDB のバージョンは > 7.1 でないと動きません Linux環境ではちゃんと動きませんでした(泣) バグ? ifaceの挙動は謎。要調査。 #7796

Slide 10

Slide 10 text

(おまけ) Tips Emacs なら、gdb-many-windowsが便利です。 テストをデバッグするときは go test ­c でバイナリができます