大家好,我是煎鱼。

上一篇文章《一个 Demo 学会使用 Go Delve 调试》我们详细介绍了 Go 语言如何使用 Delve 进行排查和调试,对于问题的解决非常的有帮助。

但调试工具肯定不止只有 Delve,今天我们来介绍第二个神器,那就是:GDB,补全我们的调试工具技术栈。

根据小伙伴们的反馈,我们后面再增加 IDE 的调试篇章。

欢迎关注煎鱼蹲下一篇:

GDB 是什么

GDB 是一个类 UNIX 系统下的程序调试工具,允许你看到另一个程序在执行时 "内部 "发生了什么,或者程序在崩溃时正在做什么。

GDB Logo

主要可以做四类事情:

  1. 启动你的程序,指定任何可能影响其行为的东西。

  2. 使你的程序在指定的条件下停止。

  3. 检查当你的程序停止时发生了什么。

  4. 改变你程序中的东西,这样你就可以试验纠正一个错误的影响,并继续了解另一个错误。

安装

如果是在 MacOS 上的话,可以直接使用 brew 安装:

brew install gdb

如果是在 Linux ,则使用自带的包管理工具进行安装即可,但需要注意安装完毕后需要在 HOME 目录进行相关配置。

安装完毕后,执行 gdb 就可以看到:

$ gdb
GNU gdb (GDB) 10.2
...
(gdb)

写此文时最新的 gdb 版本已经是 10.2 了,我也升级了上去。问题不大,还多了不少功能。

编译

我们还是使用先前的演示程序来进行调试。但由于 Go 语言的不少编译优化,因此在编译运行程序时,有以下几点需要注意:

  • go build 编译时需要增加 -gcflags=all="-N -l" 指令来关闭内联优化,方便接下来的调试。

  • 若是 MacOS,在 go build 编译时需要增加 -ldflags='-compressdwarf=false' 指令。

    • 若不禁止,则会出现 No symbol table is loaded. Use the "file" command. 的错误。

    • Go 编译默认为了减少二进制大小会默认压缩 DWARF 调试信息,但这会影响 gdb 的调试,因此需要将其关闭。

编译的命令是:

$ go build -gcflags=all="-N -l" -ldflags='-compressdwarf=false' .

输出结果:

!了鱼煎进子脑

尝试 gdb

GDB 有两种调试模式,分别是文本用户界面(Text User Interface,简称 tui)和默认的命令行模式:

// 调试界面
$ gdb -tui ./awesome-project// 命令行模式
$ gdb ./awesome-project

接下来我们使用 gdb tui 的调试模式来给大家演示功能。

我们在执行命令 gdb -tui ./awesome-project 后,窗口会切换为如下:

gdb tui 初始样子

你会发现中间提示 “No Source Available”,此时你需要继续回车两次,他就会自动加载插件支持,提示:“Loading Go Runtime support.”。

我们就可以看到具体的代码块内容,如下:

用 MacOS 的同学需要注意,如果你在断点时发现发现了如下错误:

(gdb) b main.main
Breakpoint 1 at 0x10a2ea0: file /Users/eddycjy/go-application/awesomeProject/main.go, line 15.
(gdb) r
Starting program: /Users/eddycjy/go-application/awesomeProject/hello
Unable to find Mach task port for process-id 64212: (os/kern) failure (0x5).(please check gdb is codesigned - see taskgated(8))

也就是 “please check gdb is codesigned - see taskgated(8)”,则需要重新处理证书认证和授权,是 MacOS 使用上的一个问题,具体可参考:《Codesign gdb on OSX》。

解决后,咱们的 gdb 就算是能够正确的运行起来了!

常用 gdb 命令

在 gdb 中,和 dlv 一样有常用的关键字命令。当然了,gdb 的 help all 输出非常多:

(gdb) help allCommand class: aliases
Command class: breakpointsawatch -- Set a watchpoint for an expression.
break, brea, bre, br, b -- Set breakpoint at specified location.
break-range -- Set a breakpoint for an address range.
catch -- Set catchpoints to catch events.
...

常用的关键字如下:

  • b:break 的缩写,作用是打断点,例如:main.main,可带代码行数。

  • r:run 的缩写,作用是运行程序到下一个断点处。

  • c:continue 的缩写,作用是继续执行到下一个断点。

  • s:step 的缩写,作用是单步执行,如果有所调用的方法,将会进入该方法。

  • l:list 的缩写,作用是查看对应的源码。

  • n:next 的缩写,作用是单步执行,不会进入所调用的方法,。

  • q:quit 的缩写,作用是退出。

  • info breakpoints:作用是查看所有设置的断点信息。

  • info locals:作用是查看变量信息。

  • info args:作用是查看函数的入参和出参的具体值。

  • info goroutines:作用是查看 goroutines 的信息。

  • goroutine 1 bt:作用是查看指定序号的 goroutine 调用堆栈。

进行调试

在调试上与 dlv 差不多,也是先执行关键字 b 打断点:

(gdb) b main.main
Breakpoint 1 at 0x10cbaa0: file /Users/eddycjy/go-application/awesomeProject/main.go, line 9.

也可以先执行关键字 l 查看对应的代码情况再进行做决定:

(gdb) l main.main
4  "fmt"
5
6  "github.com/eddycjy/awesome-project/stringer"
7 )
8
9 func main() {
10  fmt.Println(stringer.Reverse("脑子进煎鱼了!"))
11 }

查看对应 goroutines 正在运行的函数情况:

(gdb) info goroutines1  waiting runtime.gosched
* 13  running runtime.goexit

根据 pprof 等所得到的 goroutine 序号进行进一步的分析:

(gdb) goroutine 1 bt
#0  0x000000000040facb in runtime.gosched () at /home/user/go/src/runtime/proc.c:873
#1  0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)at  /home/user/go/src/runtime/chan.c:342
#2  0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/runtime/chan.c:423
#3  0x000000000043075b in testing.RunTests (matchString...

注意一个细节,gdb 调试是可以看到并对 runtime 包内容的代码进行断点和分析的。

也可以和 dlv 一样执行 p 关键字输出相应的值的类型、值内容:

(gdb) p re
(gdb) p t
$1 = (struct testing.T *) 0xf840688b60
(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>

与 dlv 大同小异。

总结

总体上来讲,MacOS 上使用 gdb 还是挺麻烦的,在 Linux 环境下使用 gdb 还是更方便些。

由于 dlv 和 gdb 在大致的调试上不会差距的太远,因此本文就没有过于展开。

若是对业务代码进行分析,更建议使用 dlv,也就是我们上一篇文章所讲的内容。若有 runtime 库的调试需求的话,推荐使用 gdb 来作为首要调试工具,若无这方面诉求,建议使用 dlv。

关注煎鱼,吸取他的知识 ????

你好,我是煎鱼。高一折腾过前端,参加过国赛拿了奖,大学搞过 PHP。现在整 Go,在公司负责微服务架构等相关工作推进和研发。

从大学开始靠自己赚生活费和学费,到出版 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,记得点赞!

学会使用 GDB 调试 Go 代码相关推荐

  1. 【汇编优化】之linux下如何利用gdb调试汇编代码

    1.gdb调试汇编代码 (1).假设有如下代码,test.c /*test.c*/ void main() {int a, int b, int c;a = 1;b = 2;add_mmx(a, b, ...

  2. 借助gdb调试glibc代码学习House of Orange

    转自: https://bbs.pediy.com/thread-251195.htm house_of_orange https://www.jianshu.com/p/1e45b785efc1 借 ...

  3. OAI项目GDB调试及代码分析

    OAI项目GDB调试及代码分析 如果想使用GDB调试工具对项目进行调试,首先需要在编译时加入调试信息. 在完成之前的对eNB和UE的编译之后,使用作者写的编译脚本,同时加上-g选项加入调试信息 ./c ...

  4. gdb 调试java进程_使用GDB调试JNI代码

    本文链接:http://blog.csdn.net/kongxx/article/details/7329515 最近在碰到一段JNI代码不停的出现core dump,用gdb看了一下core文件,信 ...

  5. GDB调试c++代码相关资料

    基础教学: https://www.cnblogs.com/chenmingjun/p/8280889.html https://blog.csdn.net/Stone_OverLooking/art ...

  6. GDB 调试实战之 Redis 通信协议

    时下的业界,相对于传统的关系型数据库,以 key-value 思想实现的 NoSQL 内存数据库非常流行,而提到内存数据库,很多读者第一反应就是 Redis .确实,Redis 以其高效的性能和优雅的 ...

  7. [Golang]搭建gdb调试go程序

    搭建gdb调试go程序 前言 gdb安装 更新brew 查看是否存在gdb镜像 安装gdb go build编译 gdb执行 gdb命令 gdb调试 问题整理 参考 前言 学会使用gdb进行golan ...

  8. 【java】jdb调试java代码

    jdb调试java代码 Java程序中有逻辑错误,就需要使用JDB来进行调试了.调试程序在IDE中很方便了,比如这篇博客介绍了在Intellj IDEA中调试Java程序的方法. 我们课程内容推荐在L ...

  9. 用gdb调试core文件

    GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成 ...

最新文章

  1. IEEE signal processing letters 投稿经验
  2. 定义对象或数组直接量时不同引擎对多余逗号的处理
  3. mysql 技术交流群_二进制部署MySQL(运维技术交流群:926402931,欢迎大家一起来交流。)...
  4. 【web安全】Web应用隔离防护之Web弱口令爆破
  5. Chrome 0 day漏洞利用链
  6. python读取多个文件夹_Python:从文件夹中读取多个json文件
  7. SAP License:工作中的怪现象
  8. SQLServer 2012 可视化窗口中,设置“时间”默认值为“当前时间
  9. Hi3515主板UBoot参数备份
  10. python求商和余数 考虑可能出现的异常情况_python面试题
  11. MATLAB GBK编码
  12. 用python画星空-用python画星空源代码是什么?
  13. Centos 7 x64 英文版安装
  14. 红米k50至尊版参数 红米k50至尊版评测值得买吗
  15. Linux的网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-ens33
  16. Android 支持分屏
  17. oracle怎么删除.dat,oracle删除dat文件有关问题
  18. CBD应成为所在城市群内引外联的智慧平台
  19. apache http server 停止工作_(二)http协议的网站装ssl升级成https
  20. 使用快速权重来关注最近的过去

热门文章

  1. flask简单登录注册
  2. php 中 stream_select 中的小窟窿.
  3. 面试题解(4):求排列、组合
  4. 按键精灵saystring无法使用的几种解决方案
  5. 开源软件、开源硬件、……开源餐馆来了
  6. 结对开发——电梯调度问题需求分析
  7. 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之数据篇
  8. 我决定不能贱卖自己(2010年11月13日志)
  9. Mob统计分析游戏类App详细埋点需求
  10. ssh服务优化与客户端命令使用