如何使用GDB正确调试`go test -c`生成的二进制文件?

时间:2013-12-18 01:40:46

标签: gdb go

go test命令支持-c标志,如下所示:

-c  Compile the test binary to pkg.test but do not run it.
    (Where pkg is the last element of the package's import path.)

据我所知,生成这样的二进制文件是使用GDB以交互方式运行它的方法。但是,由于测试二进制文件是通过在某些/ tmp /目录中临时组合源文件和测试文件来创建的,所以当我在gdb中运行list时会发生这种情况:

Loading Go Runtime support.
(gdb) list
42      github.com/<username>/<project>/_test/_testmain.go: No such file or directory.

这意味着我不能像以前那样愉快地检查GDB中的Go源代码。我知道可以通过将-work标志传递给go test命令来强制临时目录保留,但由于二进制文件不是在该目录中创建的,因此仍然是一个巨大的麻烦。我想知道是否有人找到了解决这个问题的干净解决方案。

4 个答案:

答案 0 :(得分:2)

不幸的是,这似乎是一个无法解决的已知问题。见这个讨论:

https://groups.google.com/forum/#!topic/golang-nuts/nIA09gp3eNU

  

我已经看到了这个问题的两个解决方案。

     

1)使用set substitute-path命令创建一个.gdbinit文件   将gdb重定向到源的实际位置。这个文件可能是   由go工具生成,但你冒着覆盖别人习惯的风险   .gdbinit文件并将go工具绑定到gdb,这看起来很糟糕   理念。

     

2)替换可执行文件中的源文件路径(指向   到/ tmp / ...)它们驻留在磁盘上的位置。这是   如果真实路径比/ tmp / ...路径短,则直截了当。   这可能需要编译器的额外支持/   链接器使这个解决方案更通用。

它在Go Google Code问题跟踪器上产生了这个问题,最终决定是:

https://code.google.com/p/go/issues/detail?id=2881

  

这很烦人,但它是许多令人讨厌的可能性中最少的。   通常,go工具不应该在源代码中涂鸦   目录,甚至可能是不可写的,它不应该是   退出后将文件留在别处。几乎没有   有趣的是_testmain.go。使用gdb进行测试的人可以继续使用   测试。主要是。

     

拉​​斯   状态:不幸

因此,简而言之,它很糟糕,虽然您可以解决它并且GDB是一个测试可执行文件,但开发团队不太可能让它变得像您一样容易。

答案 1 :(得分:0)

我还是golang游戏的新手,但是值得进行基本调试似乎有用。

只要您已经在代码中的某个断点处,就可以使用您尝试工作的列表命令。例如:

(gdb) b aws.go:54
Breakpoint 1 at 0x61841: file /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.go, line 54.
(gdb) r
Starting program: /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.test
[snip: some arnings about BinaryCache]

Breakpoint 1, github.com/stellar/deliverator/aws.imageIsNewer (latest=0xc2081fe2d0, ami=0xc2081fe3c0, ~r2=false)
    at /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.go:54
54      layout := "2006-01-02T15:04:05.000Z"
(gdb) list
49  func imageIsNewer(latest *ec2.Image, ami *ec2.Image) bool {
50      if latest == nil {
51          return true
52      }
53
54      layout := "2006-01-02T15:04:05.000Z"
55
56      amiCreationTime, amiErr := time.Parse(layout, *ami.CreationDate)
57      if amiErr != nil {
58          panic(amiErr)

这是在我项目的aws子目录中运行以下内容之后:

go test -c
gdb aws.test

作为一个额外的警告,对于可以放置断点的位置似乎非常有选择性。似乎它必须是一个表达,但结论只能通过实验。

答案 2 :(得分:0)

Go 1.5已经发布,并且仍然没有官方批准的Go调试器。使用GDB有效地调试Go程序或测试二进制文件,我没有取得多大成功。但是,我已经成功使用Delve,一个仍在进行开发的非官方调试器:https://github.com/derekparker/delve

要在调试器中运行测试代码,只需安装delve:

go get -u github.com/derekparker/delve/cmd/dlv

...然后从工作区内的调试器中启动测试:

dlv test

在调试器提示符下,您可以单步执行,设置断点等。

给它一个旋转!

答案 3 :(得分:0)

如果您愿意使用GDB以外的工具,请查看godebug。要使用它,请先安装:

go get github.com/mailgun/godebug

接下来,通过在代码中添加以下语句在某处插入断点:

_ = "breakpoint"

现在使用godebug test命令运行测试。

godebug test

它支持go test命令中的许多参数。

  -test.bench string
        regular expression per path component to select benchmarks to run
  -test.benchmem
        print memory allocations for benchmarks
  -test.benchtime duration
        approximate run time for each benchmark (default 1s)
  -test.blockprofile string
        write a goroutine blocking profile to the named file after execution
  -test.blockprofilerate int
        if >= 0, calls runtime.SetBlockProfileRate() (default 1)
  -test.count n
        run tests and benchmarks n times (default 1)
  -test.coverprofile string
        write a coverage profile to the named file after execution
  -test.cpu string
        comma-separated list of number of CPUs to use for each test
  -test.cpuprofile string
        write a cpu profile to the named file during execution
  -test.memprofile string
        write a memory profile to the named file after execution
  -test.memprofilerate int
        if >=0, sets runtime.MemProfileRate
  -test.outputdir string
        directory in which to write profiles
  -test.parallel int
        maximum test parallelism (default 4)
  -test.run string
        regular expression to select tests and examples to run
  -test.short
        run smaller test suite to save time
  -test.timeout duration
        if positive, sets an aggregate time limit for all tests
  -test.trace string
        write an execution trace to the named file after execution
  -test.v
        verbose: print additional output