打赏

dlv调试实践

dlv调试实践

案例一:通过dlv debug进行源码调试
(1.)新建main.go,并执行go mod init

package main

import (
    "fmt"
)

func main() {
    nums := make([]int, 5)
    for i := 0; i <len(nums); i++ {
        nums[i] = i * i
    }
    fmt.Println(nums)
}

(2.)执行dlv debug进入调试模式

[root@localhost demo-1]# dlv debug
Type 'help' for list of commands.

# 设置断点:main.main
(dlv) b main.main
Breakpoint 1 set at 0x49aeea for main.main() ./main.go:7

# 查看已设置的所有断点,我们发现除了我们自己设置的 main.main 函数断点外,Delve 内部已经为 panic 异常函数设置了一个断点。
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0x437a40,0x437940 for (multiple functions)() /usr/local/go/src/runtime/panic.go:1059 (0)
Breakpoint unrecovered-panic (enabled) at 0x437e00 for runtime.fatalpanic() /usr/local/go/src/runtime/panic.go:1143 (0)
        print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0x49aeea for main.main() ./main.go:7 (0)

# 查看全局变量(可通过正则参数过滤)
(dlv) vars main
runtime.main_init_done = chan bool nil
runtime.mainStarted = false

# 运行到下个断点处
(dlv) c
> main.main() ./main.go:7 (hits goroutine(1):1 total:1) (PC: 0x49aeea)
     2:
     3: import (
     4:     "fmt"
     5: )
     6:
=>   7: func main() {
     8:     nums := make([]int, 5)
     9:     for i := 0; i <len(nums); i++ {
    10:         nums[i] = i * i
    11:     }
    12:     fmt.Println(nums)

# 单步执行
(dlv) n
> main.main() ./main.go:8 (PC: 0x49aef8)
     3: import (
     4:     "fmt"
     5: )
     6:
     7: func main() {
=>   8:     nums := make([]int, 5)
     9:     for i := 0; i <len(nums); i++ {
    10:         nums[i] = i * i
    11:     }
    12:     fmt.Println(nums)
    13: }

# 查看传入函数的参数
(dlv) args
(no args)

# 查看局部变量
(dlv) locals
(no locals)

# 再下一步,初始化nums了,可以看到有局部变量了
(dlv) n
> main.main() ./main.go:9 (PC: 0x49af23)
     4:     "fmt"
     5: )
     6:
     7: func main() {
     8:     nums := make([]int, 5)
=>   9:     for i := 0; i <len(nums); i++ {
    10:         nums[i] = i * i
    11:     }
    12:     fmt.Println(nums)
    13: }
(dlv) locals
nums = []int len: 5, cap: 5, [...]
(dlv) args
(no args)

# 组和使用 break 和 condition 命令设置条件断点
(dlv) b main.go:10
Breakpoint 2 set at 0x49af42 for main.main() ./main.go:10
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0x437940,0x437a40 for (multiple functions)() /usr/local/go/src/runtime/panic.go:1059 (0)
Breakpoint unrecovered-panic (enabled) at 0x437e00 for runtime.fatalpanic() /usr/local/go/src/runtime/panic.go:1143 (0)
        print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0x49aeea for main.main() ./main.go:7 (1)
Breakpoint 2 (enabled) at 0x49af42 for main.main() ./main.go:10 (0)

# 这里设置条件断点 i 等于 3
(dlv) cond 2 i==3

# 继续 continue 执行到刚设置的条件断点,输出局部变量
(dlv) c
> main.main() ./main.go:10 (hits goroutine(1):1 total:1) (PC: 0x49af42)
     5: )
     6:
     7: func main() {
     8:     nums := make([]int, 5)
     9:     for i := 0; i <len(nums); i++ {
=>  10:         nums[i] = i * i
    11:     }
    12:     fmt.Println(nums)
    13: }
(dlv) locals
nums = []int len: 5, cap: 5, [...]
i = 3
(dlv) print nums
[]int len: 5, cap: 5, [0,1,4,0,0]

# 查看栈帧信息
(dlv) stack
0  0x000000000049af42 in main.main
   at ./main.go:10
1  0x000000000043a138 in runtime.main
   at /usr/local/go/src/runtime/proc.go:250
2  0x0000000000464cc1 in runtime.goexit
   at /usr/local/go/src/runtime/asm_amd64.s:1594
(dlv) n
> main.main() ./main.go:9 (PC: 0x49af73)
     4:     "fmt"
     5: )
     6:
     7: func main() {
     8:     nums := make([]int, 5)
=>   9:     for i := 0; i <len(nums); i++ {
    10:         nums[i] = i * i
    11:     }
    12:     fmt.Println(nums)
    13: }
(dlv) b main.go:12
Breakpoint 3 set at 0x49af82 for main.main() ./main.go:12
(dlv) c
> main.main() ./main.go:12 (hits goroutine(1):1 total:1) (PC: 0x49af82)
     7: func main() {
     8:     nums := make([]int, 5)
     9:     for i := 0; i <len(nums); i++ {
    10:         nums[i] = i * i
    11:     }
=>  12:     fmt.Println(nums)
    13: }
(dlv) print nums
[]int len: 5, cap: 5, [0,1,4,9,16]
(dlv) q

案例二:使用dlv attach 进行调试
(1.)新建main.go,并进行go mod init

package main

import (
        "log"
        "net/http"
)

func main() {
        http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
                nums := make([]int, 5)
                for i := 0; i < len(nums); i++ {
                        nums[i] = i * i
                }
                writer.Write([]byte("OK"))
        })

        err := http.ListenAndServe(":4781", nil)
        if err != nil {
                log.Fatalln(err)
        }
}

(2.) 编译,禁用编译器优化

go build -gcflags="all=-N -l" main.go
// 运行
./main

(3.)获取进程ID

ps -ef |grep main

(4.)进入调试

dlv attach $pid // pid为当前进程的pid

(5.)示例如下:

[root@localhost ~]# dlv attach 18175
Type 'help' for list of commands.

# 在main函数12行进行断点
(dlv) b main.go:12
Breakpoint 1 set at 0x74078e for main.main.func1() /home/nova000918/workspace/gocode/src/demo-1/main.go:12

# 查看断点
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0x43d380,0x43d480 for (multiple functions)() /usr/local/go/src/runtime/panic.go:1059 (0)
Breakpoint unrecovered-panic (enabled) at 0x43d840 for runtime.fatalpanic() /usr/local/go/src/runtime/panic.go:1143 (0)
        print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0x74078e for main.main.func1() /home/nova000918/workspace/gocode/src/demo-1/main.go:12 (0)

# 继续直到断点处卡住,这里发送http请求,curl http://127.0.0.1:4781/hello 会进入断点
(dlv) c
> main.main.func1() /home/nova000918/workspace/gocode/src/demo-1/main.go:12 (hits goroutine(6):1 total:1) (PC: 0x74078e)
     7:
     8: func main() {
     9:         http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
    10:                 nums := make([]int, 5)
    11:                 for i := 0; i < len(nums); i++ {
=>  12:                         nums[i] = i * i
    13:                 }
    14:                 writer.Write([]byte("OK"))
    15:         })
    16:
    17:         err := http.ListenAndServe(":4781", nil)

# 打印变量
(dlv) print nums
[]int len: 5, cap: 5, [0,0,0,0,0]

# 查看本地变量
(dlv) locals
nums = []int len: 5, cap: 5, [...]
i = 0

# 下一步
(dlv) n
> main.main.func1() /home/nova000918/workspace/gocode/src/demo-1/main.go:11 (PC: 0x7407be)
     6: )
     7:
     8: func main() {
     9:         http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
    10:                 nums := make([]int, 5)
=>  11:                 for i := 0; i < len(nums); i++ {
    12:                         nums[i] = i * i
    13:                 }
    14:                 writer.Write([]byte("OK"))
    15:         })
    16:
(dlv) n
> main.main.func1() /home/nova000918/workspace/gocode/src/demo-1/main.go:12 (hits goroutine(6):2 total:2) (PC: 0x74078e)
     7:
     8: func main() {
     9:         http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
    10:                 nums := make([]int, 5)
    11:                 for i := 0; i < len(nums); i++ {
=>  12:                         nums[i] = i * i
    13:                 }
    14:                 writer.Write([]byte("OK"))
    15:         })
    16:
    17:         err := http.ListenAndServe(":4781", nil)
(dlv) print nums
[]int len: 5, cap: 5, [0,0,0,0,0]
(dlv) locals
nums = []int len: 5, cap: 5, [...]
(dlv) print nums
[]int len: 5, cap: 5, [0,1,4,9,16]
(dlv) q
posted @ 2023-06-10 16:55  苍山落暮  阅读(103)  评论(0编辑  收藏  举报