des4maisons
des4maisons

Reputation: 1881

How to interpret Go stacktrace

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.

Upvotes: 12

Views: 7071

Answers (3)

MrGuin
MrGuin

Reputation: 37

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.

Upvotes: 1

des4maisons
des4maisons

Reputation: 1881

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 type error. 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)

Upvotes: 30

Drathier
Drathier

Reputation: 14539

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.

Upvotes: 2

Related Questions