https://www.cnblogs.com/li-peng/p/8522592.html
0 RPM
我々は、ログ出力ログを介してデータベースを追跡例外分析と問題をプログラムすることができます。しかし、時には、私はまた、より直接的なプログラムの追跡を持っていると思っていて、問題を見つけ、私たちより便利で効率的な追跡を支援するためのツールをターゲットに、最も直感的な感覚は、まだデバッガを使用しています。Linuxプラットフォーム、ネイティブC / C ++プログラムでは、我々は、我々はまた、まだデバッグ用のGDBを使用することができ、gdbでのデバッグをプログラムGolangに切り替える傾向にあります。また、実装DLV golangをデバッグするためにデバッガを使用することができます。以下では、比較し、使用GDBとDLVの私の要約です
1.準備
全体の試運転プロセスを実証するために、我々は、全体のディレクトリ構成は以下のとおり、デモプロジェクトGoDbgを準備しました
説明:
- 実行することによりgo.mod
go mod init
生成。- :如下バージョンを行く
↵バージョン2を行くjeffreyguan @ jeguan〜/ GoDbg $
バージョンgo1.12.7ダーウィン/ AMD64を行きます- 开启行くモジュール
jeffreyguan @ jeguan〜/ GoDbg $輸出| grepのGO 127↵
=オンGO111MODULE
1.1コード説明
デモデバッグ操作のために、主な機能のエントリ、および開始dbgTest.goのゴルーチンを複数main.go。
main.go:
package main
import (
"GoDbg/mylib"
"fmt"
"os"
)
func main() {
fmt.Println("Golang dbg test...")
var argc = len(os.Args)
var argv = append([]string{}, os.Args...)
fmt.Printf("argc:%d\n", argc)
fmt.Printf("argv:%v\n", argv)
var var1 = 1
var var2 = "golang dbg test"
var var3 = []int{1, 2, 3}
var var4 mylib.MyStruct
var4.A = 1
var4.B = "golang dbg my struct field B"
var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
var4.D = []string{"D1", "D2", "D3"}
mylib.DBGTestRun(var1, var2, var3, var4)
fmt.Println("Golang dbg test over")
}
次のようにdbgTest.goコードは次のとおりです。
package mylib
import (
"fmt"
"sync"
"time"
)
type MyStruct struct {
A int
B string
C map[int]string
D []string
}
func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
fmt.Println("DBGTestRun Begin!\n")
waiter := &sync.WaitGroup{}
waiter.Add(1)
go RunFunc1(var1, waiter)
waiter.Add(1)
go RunFunc2(var2, waiter)
waiter.Add(1)
go RunFunc3(&var3, waiter)
waiter.Add(1)
go RunFunc4(&var4, waiter)
waiter.Wait()
fmt.Println("DBGTestRun Finished!\n")
}
func RunFunc1(variable int, waiter *sync.WaitGroup) {
fmt.Printf("var1:%v\n", variable)
for {
if variable != 123456 {
continue
} else {
break
}
}
time.Sleep(10 * time.Second)
waiter.Done()
}
func RunFunc2(variable string, waiter *sync.WaitGroup) {
fmt.Printf("var2:%v\n", variable)
time.Sleep(10 * time.Second)
waiter.Done()
}
func RunFunc3(pVariable *[]int, waiter *sync.WaitGroup) {
fmt.Printf("*pVar3:%v\n", *pVariable)
time.Sleep(10 * time.Second)
waiter.Done()
}
func RunFunc4(pVariable *MyStruct, waiter *sync.WaitGroup) {
fmt.Printf("*pVar4:%v\n", *pVariable)
time.Sleep(10 * time.Second)
waiter.Done()
}
プログラムをデバッグする前に、我々は、ターゲットプログラムにプログラムのデバッグバージョンをコンパイルする必要があります。C / C ++プログラムでは、我々は通過しますgcc/g++
プログラムは、それによって最終的には、関連するコードを解釈することができ、デバッガが可能、デバッグ情報にコンパイルされたときにようにリンクが、他のパラメータに参加-g3、コンパイルします。:私たちはGolangプログラムをデバッグするとき同様に、我々はまた、適切なコンパイラ、リンカオプションを追加する必要があります-gcflags="-N -l"
(インライン-N -lのためのコンパイラの最適化をオフにする)デバッグ情報を生成します。GoDbgプロジェクトの指示をコンパイルします。go build -gcflags="-N -l" ~/GoDbg
2. DLVデバッガ
DLVはGolangが私のWindowsプラットフォームのデバッグでは、DLVは、ターゲットプログラムのソースコードを見つけることができない、非常に良いではないと思われるDLV現在、WindowsプラットフォームのサポートをGolangデバッガを実装している、Linuxプラットフォームの下でのデバッグGolangプログラムを使用することをお勧めします。使用DLVする前に、ローカルで必要なgo get github.com/derekparker/delve/cmd/dlv
インストール。DLV詳細な説明は、掘り下げるのgithubの上で見つけることができます。以下は、特定の命令です
ランチャー(パラメータを持ちますdlv exec ./GoDbg -- arg1 arg2
)
[jeffreyguan@jeguan GoDbg]$ dlv exec ./GoDbg -- arg1 arg2
Type 'help' for list of commands.
(dlv)
main関数にブレークポイントを設定します(b
)
(dlv) b main.main
Breakpoint 1 set at 0x40101b for main.main() ./main.go:9
デバッガを起動した後、ブレークポイントは、(継続しますc
)
(dlv) c
> main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x40101b)
4: "GoWorks/GoDbg/mylib"
5: "fmt"
6: "os"
7: )
8:
=> 9: func main() {
10: fmt.Println("Golang dbg test...")
11:
12: var argc = len(os.Args)
13: var argv = append([]string{}, os.Args...)
14:
(ブレークポイントの行番号を設定することで、ファイルにDbgTest.go b
)
(dlv) b dbgTest.go:17
Breakpoint 2 set at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17
(dlv) b dbgTest.go:23
Breakpoint 3 set at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23
(dlv) b dbgTest.go:26
Breakpoint 4 set at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26
(dlv) b dbgTest.go:29
Breakpoint 5 set at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29
すべてのブレークポイントのリストを表示bp
)(
(dlv) bp
Breakpoint unrecovered-panic at 0x429690 for runtime.startpanic() /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/panic.go:524 (0)
Breakpoint 1 at 0x40101b for main.main() ./main.go:9 (1)
Breakpoint 2 at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (0)
Breakpoint 3 at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23 (0)
Breakpoint 4 at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (0)
Breakpoint 5 at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29 (0)
DLVは一時的に文書では見られない、ブレークポイント機能を無効にし、同様のgdbdis xを提供していないようです。ただし、この機能は非常に便利ではありません。
ブレークポイントを削除しますclear x
()
(dlv) clear 5
Breakpoint 5 cleared at 0x458166 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:29
(dlv) bp
Breakpoint unrecovered-panic at 0x429690 for runtime.startpanic() /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/panic.go:524 (0)
Breakpoint 1 at 0x40101b for main.main() ./main.go:9 (1)
Breakpoint 2 at 0x457f51 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (0)
Breakpoint 3 at 0x4580d0 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:23 (0)
Breakpoint 4 at 0x458123 for GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (0)
現在位置(走行表示コードls
)
(dlv) ls
> GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:17 (hits goroutine(1):1 total:1) (PC: 0x457f51)
12: C map[int]string
13: D []string
14: }
15:
16: func DBGTestRun(var1 int, var2 string, var3 []int, var4 MyStruct) {
=> 17: fmt.Println("DBGTestRun Begin!\n")
18: waiter := &sync.WaitGroup{}
19:
20: waiter.Add(1)
21: go RunFunc1(var1, waiter)
22:
(現在のコールスタック情報を表示しますbt
)
(dlv) bt
0 0x0000000000457f51 in GoWorks/GoDbg/mylib.DBGTestRun
at ./mylib/dbgTest.go:17
1 0x0000000000401818 in main.main
at ./main.go:27
2 0x000000000042aefb in runtime.main
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:188
3 0x0000000000456df0 in runtime.goexit
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
出力変数情報print/p
()
(dlv) print var1
1
(dlv) print var2
"golang dbg test"
(dlv) print var3
[]int len: 3, cap: 3, [1,2,3]
(dlv) print var4
GoWorks/GoDbg/mylib.MyStruct {
A: 1,
B: "golang dbg my struct field B",
C: map[int]string [
1: "value1",
2: "value2",
3: "value3",
],
D: []string len: 3, cap: 3, ["D1","D2","D3"],}
GDBでデバッグ時のGDBデバッグ類推、私たちは私たちの前に見る、GDBはこの時点でVAR4、出力コンテンツVAR3を見つけることはできませんが、DLVすることができます
(第n層におけるコール・スタックに対応する命令を実行しますframe n cmd
)
(dlv) frame 1 ls
22: var4.A = 1
23: var4.B = "golang dbg my struct field B"
24: var4.C = map[int]string{1: "value1", 2: "value2", 3: "value3"}
25: var4.D = []string{"D1", "D2", "D3"}
26:
=> 27: mylib.DBGTestRun(var1, var2, var3, var4)
28: fmt.Println("Golang dbg test over")
29: }
frame 1 ls
第一層のコールスタックの実装位置に特定の表示プログラム
(の情報ゴルーチンを見るgoroutines
)
我々はdbgTest.goに実行したとき:26、我々は2ゴルーチンを開始しました
(dlv)
> GoWorks/GoDbg/mylib.DBGTestRun() ./mylib/dbgTest.go:26 (hits goroutine(1):1 total:1) (PC: 0x458123)
21: go RunFunc1(var1, waiter)
22:
23: waiter.Add(1)
24: go RunFunc2(var2, waiter)
25:
=> 26: waiter.Add(1)
27: go RunFunc3(&var3, waiter)
28:
29: waiter.Add(1)
30: go RunFunc4(&var4, waiter)
31:
この時点では、番組を視聴するには、ステータス情報をゴルーチン
(dlv) goroutines
[6 goroutines]
* Goroutine 1 - User: ./mylib/dbgTest.go:26 GoWorks/GoDbg/mylib.DBGTestRun (0x458123) (thread 9022)
Goroutine 2 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
Goroutine 3 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
Goroutine 4 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/proc.go:263 runtime.gopark (0x42b2d3)
Goroutine 5 - User: ./mylib/dbgTest.go:39 GoWorks/GoDbg/mylib.RunFunc1 (0x4583eb) (thread 9035)
Goroutine 6 - User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130 fmt.(*fmt).padString (0x459545)
観点からの情報の出力は、最初のスタートゴルーチン5は、RunFunc1、fmt.Printf今回は行われていないが行われ、その後、ゴルーチン6は、RunFunc2が行われ、それが呼び出し側の手続きfmt.Printfの内部へのアクセスを持って開始します
さらに情報をゴルーチン見る(goroutine x
)
し、オペレーティングステップ11、私は具体的な実施ゴルーチン6を参照してくださいしたいと思い、この時、実行goroutine 6
(dlv) goroutine 6
Switched from 1 to 6 (thread 9022)
これに基づき、実行bt
、あなたは例現在のコールスタックを見ることができますゴルーチン
(dlv) bt
0 0x0000000000454730 in runtime.systemstack_switch
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:245
1 0x000000000040f700 in runtime.mallocgc
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/malloc.go:643
2 0x000000000040fc43 in runtime.rawmem
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/malloc.go:809
3 0x000000000043c2a5 in runtime.growslice
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/slice.go:95
4 0x000000000043c015 in runtime.growslice_n
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/slice.go:44
5 0x0000000000459545 in fmt.(*fmt).padString
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130
6 0x000000000045a13f in fmt.(*fmt).fmt_s
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:322
7 0x000000000045e905 in fmt.(*pp).fmtString
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:518
8 0x000000000046200f in fmt.(*pp).printArg
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:797
9 0x0000000000468a8d in fmt.(*pp).doPrintf
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:1238
10 0x000000000045c654 in fmt.Fprintf
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:188
このとき、コールスタック層10の出力が、それは何も出力は、あなたがBT例えば、深さBTパラメータを追加しない出力BTの深さを設定し、当社独自のコールスタックを見つけることができますdbgTest.go自分のコールスタックプログラムの最も原始的と思われます13
(dlv) bt 13
...
10 0x000000000045c654 in fmt.Fprintf
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:188
11 0x000000000045c74b in fmt.Printf
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/print.go:197
12 0x000000000045846f in GoWorks/GoDbg/mylib.RunFunc2
at ./mylib/dbgTest.go:50
13 0x0000000000456df0 in runtime.goexit
at /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:1998
私たちは、自分が12階でスタックを呼び出しdbgTest.go参照してください。現在のゴルーチンは、私たち自身のコールスタック上ではもはやありませんが、システムの機能を呼び出す、この場合の時間は、デバッグ用のGDBを使用して、我々はこの時点で私たちを出力することができるようにする良い方法を持っていないことがわかり、私たちは必要変数情報をスタックと呼びます。DLVすることができます!この時点で単にによってframe x cmd
あなたは、出力コールスタック情報は、私たちが望むことができます
(dlv) frame 12 ls
45: time.Sleep(10 * time.Second)
46: waiter.Done()
47: }
48:
49: func RunFunc2(variable string, waiter *sync.WaitGroup) {
=> 50: fmt.Printf("var2:%v\n", variable)
51: time.Sleep(10 * time.Second)
52: waiter.Done()
53: }
54:
55: func RunFunc3(pVariable *[]int, waiter *sync.WaitGroup) {
(dlv) frame 12 print variable
"golang dbg test"
(dlv) frame 12 print waiter
*sync.WaitGroup {
state1: [12]uint8 [0,0,0,0,2,0,0,0,0,0,0,0],
sema: 0,}
どのような機能ああ!
ゴルーチン(ゴルーチン)でビューに現在どの
パラメータなしのゴルーチンは、DLVのゴルーチンがデバッグ時に私たちはあなたがゴルーチンの切り替えをしたいことを確認することができ、現在の情報を、表示されます場合には
(dlv) goroutine
Thread 9022 at ./mylib/dbgTest.go:26
Goroutine 6:
Runtime: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/runtime/asm_amd64.s:245 runtime.systemstack_switch (0x454730)
User: /home/lday/Tools/Dev_Tools/Go_Tools/go_1_6_2/src/fmt/format.go:130 fmt.(*fmt).padString (0x459545)
Go: ./mylib/dbgTest.go:26 GoWorks/GoDbg/mylib.DBGTestRun (0x458123)