英文:
How to interpret Go stacktrace
问题
当运行Go程序时,我遇到了以下堆栈跟踪:
/home/travis/.gimme/versions/go1.6.linux.amd64/src/runtime/panic.go:464 +0x3e6
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
/home/travis/gopath/src/github.com/DataDog/datadog-go/statsd/statsd.go:286 +0x11f
github.com/some/path/server.(*Server).buildAndUpdate(0xc820024068, 0xc820064600, 0x0, 0x0)
/home/travis/gopath/src/github.com/some/path/server/http.go:86 +0xf9f
created by github.com/some/path/server.(*Server).processPullRequestEvent
/home/travis/gopath/src/github.com/some/path/server/http.go:169 +0x53f
Event函数的签名是:
func (c *Client) Event(e *Event) error
可以在这里查看:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L285
Event的类型定义可以在这里查看:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L333
Client的类型定义可以在这里查看:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L59
我的问题是,我如何解释这行代码中的内存地址,以及更一般地说,涉及到类型变量作为目标和参数的堆栈跟踪?
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
当我查看了http://www.goinggo.net/2015/01/stack-traces-in-go.html(这是我能找到的唯一关于此主题的信息)时,我没有看到任何关于如何解释涉及结构体的输出的内容。
英文:
I am getting this stacktrace when running a go program:
/home/travis/.gimme/versions/go1.6.linux.amd64/src/runtime/panic.go:464 +0x3e6
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
/home/travis/gopath/src/github.com/DataDog/datadog-go/statsd/statsd.go:286 +0x11f
github.com/some/path/server.(*Server).buildAndUpdate(0xc820024068, 0xc820064600, 0x0, 0x0)
/home/travis/gopath/src/github.com/some/path/server/http.go:86 +0xf9f
created by github.com/some/path/server.(*Server).processPullRequestEvent
/home/travis/gopath/src/github.com/some/path/server/http.go:169 +0x53f
The signature of the Event function is:
func (c *Client) Event(e *Event) error
which can also be seen here: https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L285
The type definition for Event
can be seen here: https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L333
The type definition for Client
can be seen here: https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L59
My question is, how do I interpret the memory addresses on this line, and more generally, any stack traces which involve typed variables as targets and as arguments?
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
When I looked at http://www.goinggo.net/2015/01/stack-traces-in-go.html (which is the only information I was able to find on the subject), I didn't see anything about how to interpret the output when structs were involved.
答案1
得分: 27
感谢@twotwotwo的评论,我想我找到了答案。
在这行代码中:
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
- 第一个
0x0
是*Client
,确实是nil。 0xc8200c7ec8
是*Event
。- 接下来的
0x0, 0x0
表示返回类型为error
的返回值。根据http://blog.golang.org/error-handling-and-go的说明,error
是一个接口。根据http://research.swtch.com/interfaces的说明,接口被存储为两个指针。第一个指针指向接口中存储的类型信息,第二个指针指向接口中存储的数据。
我编写了以下程序,以向自己演示不同函数签名在堆栈跟踪中的显示方式:
package main
import "errors"
type X struct {
i int
}
type Y struct {
}
func (y *Y) foo(x *X) {
panic("panic in foo")
}
func (y *Y) bar(x *X) (*Y) {
panic("panic in bar")
return y
}
func (y *Y) baz(x *X) (error) {
panic("panic in baz")
return errors.New("error in baz")
}
func (y *Y) bam() {
panic("panic in bam")
}
func main() {
y := new(Y)
x := new(X)
// comment out the ones you don't want to check
y.foo(x)
y.bar(x)
y.baz(x)
y.bam()
}
当调用bam
函数时,它作用于*Y
类型,没有参数或返回值,输出包含:
main.(*Y).bam(0xc82002df48)
当调用foo
函数时,它作用于*Y
类型,接受一个*X
类型的参数,没有返回值,输出包含:
main.(*Y).foo(0xc820033f30, 0xc820033f30)
当调用bar
函数时,它作用于*Y
类型,接受一个*X
类型的参数,并返回一个*Y
类型的值,输出包含:
main.(*Y).bar(0xc820033f30, 0xc820033f30, 0x40fb46)
当调用baz
函数时,它作用于*Y
类型,接受一个*X
类型的参数,并返回一个error
类型的值(它是一个接口),输出包含:
main.(*Y).baz(0xc820033f38, 0xc820033f38, 0x0, 0x0)
英文:
Thanks to a comment from @twotwotwo, I think I figured this out.
In this line
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
- the first
0x0
is the*Client
, which is indeed nil. 0xc8200c7ec8
is*Event
- the following
0x0, 0x0
represent the return value of typeerror
.error
, according to http://blog.golang.org/error-handling-and-go, is an interface. According to http://research.swtch.com/interfaces, interfaces are stored as two pointers. The first pointer points to the type information stored in the interface, and the second pointer points to the data stored in the interface.
I wrote the following program to demonstrate to myself how different function signatures appear in a stack trace:
package main
import "errors"
type X struct {
i int
}
type Y struct {
}
func (y *Y) foo(x *X) {
panic("panic in foo")
}
func (y *Y) bar(x *X) (*Y) {
panic("panic in bar")
return y
}
func (y *Y) baz(x *X) (error) {
panic("panic in baz")
return errors.New("error in baz")
}
func (y *Y) bam() {
panic("panic in bam")
}
func main() {
y := new(Y)
x := new(X)
// comment out the ones you don't want to check
y.foo(x)
y.bar(x)
y.baz(x)
y.bam()
}
When bam
is called, which acts on *Y
but has no arguments or return value, the output contains:
main.(*Y).bam(0xc82002df48)
When foo
is called, which acts on *Y
and takes a *X
as argument, but has no return value, the output contains:
main.(*Y).foo(0xc820033f30, 0xc820033f30)
When bar
is called, which acts on *Y
, takes a *X
as argument, and returns a *Y
, the output contains:
main.(*Y).bar(0xc820033f30, 0xc820033f30, 0x40fb46)
When baz
is called, which acts on *Y
, takes *X
as argument, and returns an error
(which is an interface), the output contains:
main.(*Y).baz(0xc820033f38, 0xc820033f38, 0x0, 0x0)
答案2
得分: 2
你遇到的是空指针解引用错误(nil pointer dereference)。(除非你正在使用unsafe
包,但你可能不应该去碰它,所以我假设你没有使用。)
从github.com/some/path/server/http.go:86
调用func (c *Client) Event(e *Event) error
时,看起来e
参数是nil
。
英文:
What you have is a nil pointer dereference. (Unless you are using package unsafe
, which you probably shouldn't touch, so I'm assuming you're not.)
It looks like the e
argument to func (c *Client) Event(e *Event) error
is nil
when called from github.com/some/path/server/http.go:86
.
答案3
得分: 1
基本上:方法接收器(如果有),显式参数(如果有),返回值(如果有)。
要理解堆栈跟踪,首先需要了解Go的数据结构的内部表示。例如,切片类型的参数在函数的堆栈跟踪中有三个组成部分,因此有三个值:data(一个指针),len(一个int),cap(一个int)。
你可能会发现这篇文章有用。
英文:
Basicly: method receiver(if any), explicit arguments(if any), return values(if any).
To understand the stack traces, you need to first understand Go's data structures' internal representation. For example, arguments of slice type have three components thus three values in the stack trace of the func: data(a pointer), len(an int), cap(an int).
You might find this article useful.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论