golang学习系列——4. 程序调试

GDB 调试:

注意事项

1. golang1.3之后的版本,对于支持gdb调试存在很大的问题。产生这个问题的原因是,golang的runtime没有完整的被gdb支持。最新比较完整支持gdb调试的版本是golang 1.2.2,但是也有个别问题存在。

2. 在编译go程序的时候,需要关闭内联优化:** -gcflags “-N -l”**。可以在go get/build/test的时候指定这个参数。

3. 有两种方式可以下断点:

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

运行实例

1. 启动GDB

➜  ~  gdb ./test
GNU gdb (Ubuntu 7.7-0ubuntu3) 7.7
Copyright (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)

2. 以模块名的方式查看源码

(gdb) l main.main
9       r = fmt.Sprintf("test: %s %d", s, x)
10      runtime.Breakpoint()
11      return r
12  }
13
14  func main() {
15      s := "haha"
16      i := 1234
17      println(test(s, i))

3. 以文件名加行号的方式查看源码

(gdb) l /home/roy/test.go:1
1   package main
2
3   import (
4       "fmt"
5       "runtime"
6   )
7
8   func test(s string, x int) (r string) {
9       r = fmt.Sprintf("test: %s %d", s, x)
10      runtime.Breakpoint()

4. 设置断点

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

5. 启动进程,触发断点: (n 单步执行,c执行到下一个断点)

(gdb) run
Starting program: /home/roy/test

Breakpoint 2, main.main () at /home/roy/test.go:14
14  func main() {

6. 查看goroutines

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

7. 查看指定goroutine的调用堆栈

(gdb) goroutine 1 bt
Python 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) n

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

此时,我们需要重启gdb的调试,否则执行任何命令都会报告段错误。

8. 打印栈帧信息

(gdb) info frame
Stack 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

9. 查看局部变量

(gdb) info locals
i = 1234
s = "haha"

10. 以Pretty-Print的方式打印变量

(gdb) p s
$1 = "haha"

11. 获取对象的长度,即cap

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

12. 查看对象类型

(gdb) whatis i
type = int
(gdb) whatis s
type = struct string

13. 输入n单步执行到进入test函数,查看传递给函数的参数

(gdb) n
main.test (s="haha", x=1234, r="test: haha 1234") at /home/roy/test.go:11
11      return r
(gdb) info args
s = "haha"
x = 1234
r = "test: haha 1234"

14. 输入q,或者Ctrl-D退出

(gdb) q
A debugging session is active.

    Inferior 1 [process 6079] will be killed.

Quit anyway? (y or n) y

打印信息

鉴于 gdb 对于 golang 的支持不完善,以及用 gdb 调试比较麻烦。

所以个人建议:要么用 ide 自带的调试功能,要么我用打印信息。(惊不惊喜,意不意外?写了那么多 gdb 的,我不用它)

  1. 在合适的位置使用打印语句输出相关变量的值(print/println 和 fmt.Print/fmt.Println/fmt.Printf)。

  2. 在 fmt.Printf 中使用下面的说明符来打印有关变量的相关信息:

    • %+v 打印包括字段在内的实例的完整信息
    • %#v 打印包括字段和限定类型名称在内的实例的完整信息
    • %T 打印某个类型的完整说明
  3. 使用 panic 语句来获取栈跟踪信息(直到 panic 时所有被调用函数的列表)。

  4. 使用关键字 defer 来跟踪代码执行过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值