繁体   English   中英

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

[英]How to properly debug a binary generated by `go test -c` using GDB?

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命令来强制保留临时目录,但是由于在该目录等中未创建二进制文件,因此仍然很麻烦。 我想知道是否有人找到解决此问题的干净方法。

不幸的是,这似乎是一个已知问题,不会解决。 查看此讨论:

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

我已经看到了两种解决此问题的方法。

1)使用set replace-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可以测试可执行文件,但是开发团队不太可能像它对您一样容易。

Go 1.5已经发布,目前还没有官方认可的Go调试器。 使用GDB来有效调试Go程序或测试二进制文件并没有取得多少成功。 但是,我使用了仍在开发中的非官方调试器Delve取得了成功: https//github.com/derekparker/delve

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

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

...,然后从工作空间中的调试器中启动测试:

dlv test

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

旋转一下!

我仍然对golang游戏不熟悉,但是值得进行基本调试。

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

(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

另外需要注意的是,断点放置位置似乎非常有选择性。 似乎它必须是一种表达,但结论只是通过实验。

如果您愿意使用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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM