dlv debug Type 'help' for list of commands. (dlv) help The following commands are available:
Running the program: call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!) continue (alias: c) --------- Run until breakpoint or program termination. next (alias: n) ------------- Step over to next source line. rebuild --------------------- Rebuild the target executable and restarts it. It does not work if the executable was not built by delve. restart (alias: r) ---------- Restart process. step (alias: s) ------------- Single step through program. step-instruction (alias: si) Single step a single cpu instruction. stepout (alias: so) --------- Step out of the current function.
Manipulating breakpoints: break (alias: b) ------- Sets a breakpoint. breakpoints (alias: bp) Print out info for active breakpoints. clear ------------------ Deletes breakpoint. clearall --------------- Deletes multiple breakpoints. condition (alias: cond) Set breakpoint condition. on --------------------- Executes a command when a breakpoint is hit. toggle ----------------- Toggles on or off a breakpoint. trace (alias: t) ------- Set tracepoint. watch ------------------ Set watchpoint.
Viewing program variables and memory: args ----------------- Print function arguments. display -------------- Print value of an expression every time the program stops. examinemem (alias: x) Examine raw memory at the given address. locals --------------- Print local variables. print (alias: p) ----- Evaluate an expression. regs ----------------- Print contents of CPU registers. set ------------------ Changes the value of a variable. vars ----------------- Print package variables. whatis --------------- Prints type of an expression.
Listing and switching between threads and goroutines: goroutine (alias: gr) -- Shows or changes current goroutine goroutines (alias: grs) List program goroutines. thread (alias: tr) ----- Switch to the specified thread. threads ---------------- Print out info for every traced thread.
Viewing the call stack and selecting frames: deferred --------- Executes command in the context of a deferred call. down ------------- Move the current frame down. frame ------------ Set the current frame, or execute command on a different frame. stack (alias: bt) Print stack trace. up --------------- Move the current frame up.
Other commands: config --------------------- Changes configuration parameters. disassemble (alias: disass) Disassembler. dump ----------------------- Creates a core dump from the current process state edit (alias: ed) ----------- Open where you are in $DELVE_EDITOR or $EDITOR exit (alias: quit | q) ----- Exit the debugger. funcs ---------------------- Print list of functions. help (alias: h) ------------ Prints the help message. libraries ------------------ List loaded dynamic libraries list (alias: ls | l) ------- Show source code. source --------------------- Executes a file containing a list of delve commands sources -------------------- Print list of source files. target --------------------- Manages child process debugging. transcript ----------------- Appends command output to a file. types ---------------------- Print list of types
Type help followed by a command for full documentation. (dlv)
(dlv) breakpoints Breakpoint runtime-fatal-throw (enabled) at 0x103b500,0x103b600 for (multiple functions)() <multiple locations>:0 (0) Breakpoint unrecovered-panic (enabled) at 0x103b9a0 for runtime.fatalpanic() /usr/local/Cellar/go/1.20.6/libexec/src/runtime/panic.go:1145 (0) print runtime.curg._panic.arg Breakpoint 1 (enabled) at 0x19aa9e5 for main.main() ./main.go:32 (0)
我想设置的是main.go的第32行,
1 2 3
31 for i := 0; i < 3; i++ { 32 fmt.Println(i) 33 }
在i的值为2时出现断点。
执行如下命令:
1
condition 1 i==2
这里的1是断点ID,后面i==2是断点出现的条件。
查看断点
在调试模式下输入:
1
breakpoints
在不人为设置断点的默认情况下,会有一个panic函数断点:
1 2 3 4
(dlv) breakpoints Breakpoint runtime-fatal-throw (enabled) at 0x103b600,0x103b500 for (multiple functions)() <multiple locations>:0 (0) Breakpoint unrecovered-panic (enabled) at 0x103b9a0 for runtime.fatalpanic() /usr/local/Cellar/go/1.20.6/libexec/src/runtime/panic.go:1145 (0) print runtime.curg._panic.arg
调试
没有函数调用的情况
下面是一个示范,给一个例子进行调试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
package main
import ( "fmt" )
funcmain() { nums := make([]int, 5) for i := 0; i < 5; i++ { nums[i] = i * i } fmt.Println(nums) for i := 0; i < 5; i++ { nums = append(nums, i) } fmt.Println(nums) }
通过dlv debug进入调试模式
1 2
> dlv debug Type 'help' for list of commands.
在main.go的第10行设置断点:
1 2
(dlv) break main.go:10 Breakpoint 1 set at 0x10b5c6f for main.main() ./main.go:10
执行c会在下一个断点处中止:
1 2 3 4 5 6 7 8 9 10 11 12 13
(dlv) c > main.main() ./main.go:10 (hits goroutine(1):1 total:1) (PC: 0x10b5c6f) 5: ) 6: 7: func main() { 8: nums := make([]int, 5) 9: for i := 0; i < 5; i++ { => 10: nums[i] = i * i 11: } 12: fmt.Println(nums) 13: for i := 0; i < 5; i++ { 14: nums = append(nums, i) 15: }
(dlv) c > main.main() ./main.go:10 (hits goroutine(1):4 total:4) (PC: 0x10b5c6f) 5: ) 6: 7: func main() { 8: nums := make([]int, 5) 9: for i := 0; i < 5; i++ { => 10: nums[i] = i * i 11: } 12: fmt.Println(nums) 13: for i := 0; i < 5; i++ { 14: nums = append(nums, i) 15: } (dlv) c > main.main() ./main.go:10 (hits goroutine(1):5 total:5) (PC: 0x10b5c6f) 5: ) 6: 7: func main() { 8: nums := make([]int, 5) 9: for i := 0; i < 5; i++ { => 10: nums[i] = i * i 11: } 12: fmt.Println(nums) 13: for i := 0; i < 5; i++ { 14: nums = append(nums, i) 15: } (dlv) c [0 1 4 9 16] > main.main() ./main.go:14 (hits goroutine(1):1 total:1) (PC: 0x10b5d5a) 9: for i := 0; i < 5; i++ { 10: nums[i] = i * i 11: } 12: fmt.Println(nums) 13: for i := 0; i < 5; i++ { => 14: nums = append(nums, i) 15: } 16: fmt.Println(nums) 17: } 18: 19: func cleanPath(p string) string { (dlv) print i 3
可以看到触发14行的断点时,i的就是3,达到了满足断点触发的条件。
接下来继续运行c命令,程序推出:
1 2 3
(dlv) c [0 1 4 9 16 0 1 2 3 4] Process 77401 has exited with status 0
查看有函数调用的情况
在函数内部设置断点
想要查看函数内部的运行情况,可以在函数内部设置断点。
以下面这个源代码的调试为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
package main
import ( "fmt" )
func main() { i := 10 j := 20 r := multi(i, j) fmt.Println(r) }
func multi(i, j int) int { r := i * j return r }
现在进入multi函数前设置断点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
dlv debug Type 'help' for list of commands. (dlv) break main.go:9 Breakpoint 1 set at 0x10b5c21 for main.main() ./main.go:9 (dlv) c > main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x10b5c21) Warning: listing may not match stale executable 4: "fmt" 5: ) 6: 7: func main() { 8: i := 10 => 9: j := 20 10: r := multii(i, j) 11: fmt.Println(r) 12: } 13: 14: func multii(i, j int) int {
(dlv) c > main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x10b5c21) 4: "fmt" 5: ) 6: 7: func main() { 8: i := 10 => 9: j := 20 10: r := multi(i, j) 11: fmt.Println(r) 12: } 13: 14: func multi(i, j int) int { (dlv) break main.go:15 Breakpoint 2 set at 0x10b5d00 for main.multi() ./main.go:15 (dlv) c > main.multi() ./main.go:15 (hits goroutine(1):1 total:1) (PC: 0x10b5d00) 10: r := multi(i, j) 11: fmt.Println(r) 12: } 13: 14: func multi(i, j int) int { => 15: r := i * j 16:
可以看到此时到达了函数内部。
在函数内部,有不同的命令可以用,args可以查看函数接收的参数是什么
1 2 3 4
(dlv) args i = 10 j = 20 ~r0 = 0
stack查看调用栈:
1 2 3 4 5 6 7 8 9
(dlv) stack 0 0x00000000010b5d00 in main.multi at ./main.go:15 1 0x00000000010b5c39 in main.main at ./main.go:10 2 0x00000000010394f3 in runtime.main at /usr/local/Cellar/go/1.20.6/libexec/src/runtime/proc.go:250 3 0x0000000001066b61 in runtime.goexit at /usr/local/Cellar/go/1.20.6/libexec/src/runtime/asm_amd64.s:1598
(dlv) n 200 > main.main() ./main.go:12 (PC: 0x10b5cba) 7: func main() { 8: i := 10 9: j := 20 10: r := multi(i, j) 11: fmt.Println(r) => 12: } 13: 14: func multi(i, j int) int { 15: r := i * j 16: return r 17: } (dlv) c Process 11724 has exited with status 0