用Go语言已经有一段时间了,总结一下如何用GDB来调试它!

ps:网上有很多文章都有描述,但是都不是很全面,这里将那些方法汇总一下

GDB简介 

GDB是GNU开源组织发布的⼀一个强⼤大的UNIX下的程序调试⼯工具。或许,各位⽐比较喜欢那种图形界⾯面⽅方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会 发现GDB这个调试⼯工具有⽐比VC、BCB的图形化调试器更强⼤大的功能。所谓“⼨寸有所⻓长,尺有所短”就是这个道理。

目前支持的语言 (GNU gdb (GDB) 7.8)
进入 gdb之后输入 set language 可以查看支持的语言列表

$ gdb
(gdb) set language
Requires an argument. Valid arguments are auto, local, unknown, ada, c, c++, asm, minimal, d, fortran, objective-c, go, java, modula-, opencl, pascal.
(gdb)

准备工作

首先看下已经编写好的一个简单的go语言程序

➜  go-debug-example  tree
.
├── lib
│   └── calc.go
└── main.go directory, files

main.go

package main

import (
"fmt"
"github.com/beyondblog/go-debug-example/lib"
"os"
"runtime"
//"runtime/debug"
) func main() {
var modify string
argsLen := len(os.Args)
if argsLen < {
fmt.Printf("Usage go-debug-example [username] \r\n")
os.Exit(-)
}
username := os.Args[]
var password string
fmt.Printf("%s welcome!\r\nplease input password:", username)
fmt.Scanf("%s", &password)
fmt.Printf("%s password: %s\r\n", username, password) sum :=
for i := ; i < ; i++ {
sum += i
if i == {
modify = "modify!"
}
} fmt.Println(lib.Add(sum, )) runtime.Breakpoint()
//debug.PrintStack()
fmt.Println(sum)
fmt.Println(modify)
}

calc.go

package lib

func Add(a int, b int) int {
c :=
a = c + b
return a + b
}

程序很简单,就是从命令行获取一个值然后做了写简单的计算,最后输出一下

那么我们编译一下 ^.^

go build
然后生成了我们要的文件,然后我们执行 gdb go-debug-example

输入 run(简写r)命令运行程序,这个时候可能会有一个提示

(gdb) run
Starting program: /Users/****/gopath/src/github.com/beyondblog/go-debug-example/go-debug-example
Unable to find Mach task port for process-id : (os/kern) failure (0x5).
(please check gdb is codesigned - see taskgated())

如果你用的是OSX应该就能看到这个,这个提示签名错误,
Darwin kernel出于安全考虑,在没有特殊授权的情况下不允许gdb调试任何程序,因为可以调试就掌握了进程的控制权。不过如果是root用户就没有这个问题,不过谁愿意用root来调试程序呢
解决办法可以通过[这篇文章](http://blog.csdn.net/powerlly/article/details/30323015)来查看
或者启动gdb的时候 加个sudo呗,那么重新来过

sudo gdb go-debug-example
r
然后提示了

(gdb) r
Starting program: /Users/****/gopath/src/github.com/beyondblog/go-debug-example/go-debug-example
Usage go-debug-example [username]
[Inferior (process ) exited with code ]

程序成功执行,但是我们那个Go程序提示需要加一个参数才能够继续下去
可以直接 r [参数] 获取在 使用 set args [参数]

ps:可以用 r > file 或者 >> file 支持结果重定向到文件

set args 这个命令是设置参数信息
show args 查看启动的参数信息

既然调试代码就能看到源码啊,使用list(简写l) 命令查看代码执行位置附近10行

(gdb) list
package main import (
"fmt"
"github.com/beyondblog/go-debug-example/lib"
"os"
"runtime"
//"runtime/debug"
) (gdb)

默认显示了10行 查看更多的话可以在输入list 或者敲回车(gdb 会默认记住上一个指令然后回车就能继续执行了 -,- )
查看list帮助

(gdb) help list
List specified function or line.
With no argument, lists ten more lines after or around previous listing.
"list -" lists the ten lines before a previous ten-line listing.
One argument specifies a line, and ten lines are listed around that line.
Two arguments with comma between specify starting and ending lines to list.
Lines can be specified in these ways:
LINENUM, to list around that line in current file,
FILE:LINENUM, to list around that line in that file,
FUNCTION, to list around beginning of that function,
FILE:FUNCTION, to distinguish among like-named static functions.
*ADDRESS, to list around the line containing that address.
With two args if one is empty it stands for ten lines away from the other arg.
(gdb)

大概的意思就是

    list      //查看第20行周围的10行

    list -         //查看上一个list代码之前的10行

    list ,    //查看1到100行 如果不足100行就显示末尾

    list main     //查看main函数
执行这个命令的时候会发现显示的不是main函数的信息而是一段汇编代码 (gdb) list main
MOVQ (SP), DI // argc
MOVQ $main(SB), AX
JMP AX TEXT main(SB),NOSPLIT,$-
MOVQ $runtime·rt0_go(SB), AX
JMP AX
(gdb) 大概的意思是go程序的真正入口点应该是这玩意 (ps: $main(SB) SB = ,=)
这个时候用 list main.main 即可 意思是查看main.go文件里面main函数附近的10行 list main.main, //查看从main文件中main函数中从函数开始到第20行 l main.go: //以 :方式查看指定文件源码
l calc.go: //查看calc.go的源码
l github.com/beyondblog/go-debug-example/lib/calc.go: //绝对文件路径查看 还可以搜索代码用 search text //可显示在当前文件中包含text串的下一行
reverse-search text //显示包含text 的前一行
forward-search text //不解释

现在设置一个断点看看,命令是 break (简写b) 后面的参数和list命令后面的参数大致一样,例如

    b main.main //在main下设置断点
b //在11行设置断点 //查看断点
info breakpoints (gdb) info breakpoints
Num Type Disp Enb Address What
breakpoint keep y 0x0000000000002000 in main.main at /Users/****/github.com/ beyondblog/go-debug-example/main.go:
breakpoint keep y 0x000000000000203b in main.main at /Users/****/github.com/ beyondblog/go-debug-example/main.go: 能够显示详细的信息,注意这上面有个End 是是否启用的意思可以使用
disable Num或者 enable Num 来设置断点是否有效 //删除断点 delete(简写d) //不带参数清空所有断点
d //删除编号为1的断点 //条件断点 非常实用!
b Num if [表达式] //在第Num设置断点当满足表达式的条件是触发
例如
b if i=

下面让程序运行起来

Argument list to give program being debugged when it is started is "".
(gdb) set args beyond
(gdb) show args
Argument list to give program being debugged when it is started is "beyond".
(gdb) b main.main
Breakpoint at 0x2000: file /Users/****/gopath/src/github.com/beyondblog/go-debug-example/main.go, line .
(gdb) r
Starting program: /Users/****/gopath/src/github.com/beyondblog/go-debug-example/go-debug-example beyond
[New Thread 0x1617 of process ]
[New Thread 0x1803 of process ] Breakpoint , main.main () at /Users/****/github.com/beyondblog/go-debug-example/main.go:
func main() {
(gdb) n
var modify string
(gdb)
    next(简写n)         //下一步
step(简写s) //单步执行,例如跳进函数内部
finish //退出该函数返回到它的调用函数中
until(简写u) //直接执行到下一行,如果遇到循环语句,会执行完当前循环
u Num //指哪打哪,继续执行直到Num行时触发断点
continue(简写c) //从断点开始继续执行 例如
(gdb) u
beyond welcome!
please input password:
main.main () at /Users/****/gopath/src/github.com/beyondblog/go-debug-example/main.go:
fmt.Printf("%s password: %s\r\n", username, password)
(gdb) frame(简写f) //查看当前命令帧,也就是看当前程序执行到那一行了 info locals //查看当前变量信息
(gdb) info locals
sum =
&password = 0x2081b4210
username = 0x7fff5fbffc58 "beyond"
modify = 0x0 ""
这个时候会发现,怎么有些变量没显示出来,官方说默认的编译会给调试带来一些不变的优化,可以使用
go build -gcflags "-N -l" 来关闭这个优化从而方便调试
那么重新编译后运行在 info local 下
(gdb) info locals
sum =
i =
argsLen =
&password = 0x2081b4210
username = 0x7fff5fbffc58 "beyond"
modify = 0x0 "" 会发现 i 和 sum的值不是一个预期的0,这个是我们程序还没执行到初始化那一块,默认取的一个随机数吧
ps: 虽然从代码上看好像程序在这个时候还没有声明 i 和 sum,但是最终生成的go语言程序应该是有自己的优化自动声明了 类似的还有很多种命令就不一一介绍了,下面来个逼格高的
layout src 或者 ctrl x + ctrl a 启动 tui 界面
或者启动gdb 的时候加上 tui参数
例如
gdb -tui

逼格满满有木有哇!

tui有4中窗口模式分别是

    command 命令窗口. 可以键入调试命令
source 源代码窗口. 显示当前行,断点等信息
assembly 汇编代码窗口
register 寄存器窗口

详细的说明:https://sourceware.org/gdb/current/onlinedocs/gdb/TUI.html#TUI

这个时候想查看源代码可以用list 也可以用方向键

首先先将窗口的焦点设置到源代码窗口上

    focus src

然后就可以用方向键来查看源代码了,这个时候如果想回到command窗口同理只需要

    focus cmd

这个时候你执行命令n 会有一个文本的图形界面还显示

gdb 还有一个特别有用的jump命令,它允许强制的跳转,不会改变栈的结构.
意思就是 如果我的程序运行到第10行的时候我现在想回到第5行调试看看又不想重新运行一边
举个栗子
现在我们执行到第32行,直接输入命令

u 

    B+>│              fmt.Println(lib.Add(sum, ))

    s //单步进入

        func Add(a int, b int) int {
(gdb) list
package lib func Add(a int, b int) int {
c :=
a = c + b
return a + b
}
(gdb) n
c :=
(gdb) n
a = c + b
(gdb) f
# github.com/beyondblog/go-debug-example/lib.Add (a=, b=, ~r2=) at /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go:
a = c + b

这个时候已经到了第5行 我现在要回到第4行,jump 4 发现没有用因为jump是跳转到第4行开始执行,但不触发断点所以一般先在要跳转的行号哪儿设置个断点

    github.com/beyondblog/go-debug-example/lib.Add (a=, b=, ~r2=) at /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go:
func Add(a int, b int) int {
(gdb) b
Breakpoint at 0x50fed: file /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go, line .
(gdb) n Breakpoint , github.com/beyondblog/go-debug-example/lib.Add (a=, b=, ~r2=) at /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go:
c :=
(gdb) n
a = c + b
(gdb) n
return a + b
(gdb) jump
Continuing at 0x50fed. Breakpoint , github.com/beyondblog/go-debug-example/lib.Add (a=, b=, ~r2=) at /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go:
c :=
(gdb) n
a = c + b
(gdb)
return a + b
(gdb) jump
Continuing at 0x50fed. Breakpoint , github.com/beyondblog/go-debug-example/lib.Add (a=, b=, ~r2=) at /Users/****/github.com/beyondblog/go-debug-example/lib/calc.go:
c :=
(gdb) //还可以使用set 命令来设置变量的值 例如
set b =

最后附上gdb的官方文档
https://sourceware.org/gdb/current/onlinedocs/gdb/

这个example的链接

https://github.com/beyondblog/go-debug-example.git

----
参考文章:

[0] http://blog.csdn.net/haoel/article/details/2879

[1] http://blog.studygolang.com/2012/12/gdb%E8%B0%83%E8%AF%95go%E7%A8%8B%E5%BA%8F/

[2] http://laokaddk.blog.51cto.com/368606/945057/

[3] http://blog.csdn.net/lwbeyond/article/details/7839225

使用GDB调试Go语言的更多相关文章

  1. GDB调试D语言

    GDB7.2后开始支持对D语言的调试 GUI前端 http://beej.us/guide/bggdb/#compiling GDB教程 http://blog.csdn.net/haoel/arti ...

  2. c语言之gdb调试。

    1.此文档演示如何使用gdb调试c语言代码. 代码如下: #include <stdio.h> /*函数声明*/ void digui(int n); int main() { ; dig ...

  3. 比较全面的gdb调试命令 (转载)

    转自http://blog.csdn.net/dadalan/article/details/3758025 用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形 ...

  4. 经典的GDB调试命令

    在你调试程序时,当程序被停住时,你可以使用print命令(简写命令为p),或是同义命令inspect来查看当前程序的运行数据.print命令的格式是: printprint /是表达式,是你所调试的程 ...

  5. GDB 调试解析

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

  6. 经典的GDB调试命令,包括查看变量,查看内存

    经典的GDB调试命令,包括查看变量,查看内存 在你调试程序时,当程序被停住时,你可以使用print命令(简写命令为p),或是同义命令inspect来查看当前程序的运行数据.print命令的格式是: p ...

  7. Linux下用gdb 调试、查看代码堆栈

      Linux中用gdb 查看代码堆栈的信息 core dump 一般是在segmentation fault(段错误)的情况下产生的文件,需要通过ulimit来设置才会得到的. 调试的话输入: gd ...

  8. windows下用eclipse+goclipse插件+gdb搭建go语言开发调试环境

    windows下用eclipse+goclipse插件+gdb搭建go语言开发调试环境   http://rongmayisheng.com/post/windows%E4%B8%8B%E7%94%A ...

  9. 【嵌入式开发】C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

随机推荐

  1. Mvc HtmlHelper 方法扩展 DropDownListFor

      项目中遇到表单提交中遇到枚举,忽然想起1年前的1小段代码结合HtmlHelper在扩展一下 便于开发中使用 public static class HtmlHelperExtensions { p ...

  2. OpneCv2.x 模块结构

    转自:http://blog.csdn.net/huang9012/article/details/21811271 之前啃了不少OpenCV的官方文档,发现如果了解了一些OpenCV整体的模块架构后 ...

  3. html传值 location.search取

    $(function() { var url = decodeURI(location.search); if (url.indexOf("?") != -1) { var str ...

  4. 学习微信小程序之css11内外边距集合

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Java EE之servlet处理表单提交的请求

    1.在源包下新建一个Servlet页,取名为LoginServlet: package weinidingServlet;                            //该Servlet所 ...

  6. 活动助手Beta用户试用报告

    用户试用报告 1.面向参与者用户 1.1 日常参加各类学习(水综测)活动中,有没有遇到以下问题: (1) 信息来源混乱,不知道靠不靠谱 (2) 每次报名都要重新填写自己的学号手机号,有时候填错了就没综 ...

  7. [软件推荐]快速文件复制工具(Limit Copy) V4.0 绿色版

    快速文件复制工具(Limit Copy)绿色版是一款智能变频超快复制绿色软件. 快速文件复制工具(Limit Copy)功能比较完善,除了文件复制还可以智能变频,直接把要复制的文件拖入窗口即可,无需手 ...

  8. 51nod算法马拉松15

    智力彻底没有了...看来再也拿不到奖金了QAQ... A B君的游戏 因为数据是9B1L,所以我们可以hash试一下数据... #include<cstdio> #include<c ...

  9. ThinkPHP框架的一些基础应用

    这是俺滴师傅给俺传授了的知识,特在此分享. TP框架,做PHP开发的都应该有所耳闻.下面,我们就来说说入口文件的生成: 创建新项目时,首先,在目录文件下创建一个新的文件夹.然后将Thinkphp框架文 ...

  10. Mac 终端 Linux 命令总结(简单命令)

    目录操作 命令名 功能描述 使用举例 mkdir 创建一个目录 mkdir dirname rmdir 删除一个目录 rmdir dirname mvdir 移动或重命名一个目录 mvdir dir1 ...