Weird behavior - runtime error: invalid memory address or nil pointer dereference

1,130 views
Skip to first unread message

Sascha Matzke

unread,
Jan 20, 2012, 6:37:30 AM1/20/12
to golan...@googlegroups.com
Hi,

I stumbled over some weird behavior with the latest weekly.

2012/01/20 12:28:22 http: panic serving 10.180.156.122:61722: runtime
error: invalid memory address or nil pointer dereference
/home/sascha/Development/Go/go/src/pkg/net/http/server.go:575 (0x809401c)
/home/sascha/Development/Go/go/src/pkg/runtime/proc.c:1386 (0x805df08)
/home/sascha/Development/Go/go/src/pkg/runtime/runtime.c:128 (0x805e94c)
/home/sascha/Development/Go/go/src/pkg/runtime/thread_linux.c:198 (0x80615b3)
/home/sascha/Development/ServiceBus/gsb-logserver/src/logserver/logserver_util.go:224
(0x804dd8e)
/home/sascha/Development/ServiceBus/gsb-logserver/src/logserver/logserver_intstats.go:82
(0x804b1de)
/home/sascha/Development/ServiceBus/gsb-logserver/src/logserver/logserver_intstats.go:154
(0x804c58f)
/home/sascha/Development/Go/go/src/pkg/net/http/server.go:909 (0x808a253)
/home/sascha/Development/Go/go/src/pkg/net/http/server.go:655 (0x8089554)
/home/sascha/Development/Go/go/src/pkg/runtime/proc.c:258 (0x805c3ae)

Line 224 in logserver_util.go looks like this:

func (c *Counter) TimeSeries() *TimeSeries {
fmt.Println("C:", c)
return c.ts // <- line 224
}

Counter is defined as:

type Counter struct {
value int
ts *TimeSeries
lock *sync.Mutex
ticker *time.Ticker
day int
}

Line 82 in logserver_util.go:

if se.value != nil {
ts := se.value.TimeSeries()
....
}

Where se.value is an *Counter.

The Println statement results in the following output:

C: <nil>

How can se.value be != nil and c == nil?

Best regards,

Sascha
--
Through the darkness of future past
the magician longs to see
One chants out between two worlds
Fire walk with me.

Dmitry Vyukov

unread,
Jan 20, 2012, 6:42:01 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
Perhaps it is mutated concurrently by another goroutine?
 

Dave Cheney

unread,
Jan 20, 2012, 6:45:26 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
se.value is most likely nil, you can call methods on nil pointers.

http://play.golang.org/p/m8lzAQN2xv

Dave

Dave Cheney

unread,
Jan 20, 2012, 6:55:37 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
Whoops, here is the correct example

http://play.golang.org/p/0RQNesP2IC

Sascha Matzke

unread,
Jan 20, 2012, 6:56:08 AM1/20/12
to golan...@googlegroups.com
Hi,

On Fri, Jan 20, 2012 at 12:45, Dave Cheney <da...@cheney.net> wrote:
> se.value is most likely nil, you can call methods on nil pointers.

It was nil. The se.value struct-field is defined to be an interface.

How do I check an interface field for nil?

se.value != nil obviously failed to do that.

Regards,

Jan Mercl

unread,
Jan 20, 2012, 7:06:06 AM1/20/12
to golan...@googlegroups.com


On Friday, January 20, 2012 12:56:08 PM UTC+1, Sascha Matzke wrote:

se.value != nil obviously failed to do that.

E.g. 
// if 'se' has type interface{}. Otherwise 'ok' could be sometimes dropped depending on type of 'se'.
if p, ok := se.(*Counter); ok && p != nil { ts := p.value.TimeSeries() }

chris dollin

unread,
Jan 20, 2012, 7:36:01 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
On 20 January 2012 11:56, Sascha Matzke <sascha...@didolo.org> wrote:
> Hi,
>
> On Fri, Jan 20, 2012 at 12:45, Dave Cheney <da...@cheney.net> wrote:
>> se.value is most likely nil, you can call methods on nil pointers.
>
> It was nil. The se.value struct-field is defined to be an interface.
>
> How do I check an interface field for nil?
>
> se.value != nil obviously failed to do that.

No, it did not fail. se.value was a non-nil interface value. This
non-nil value says "I am of type *Counter, and I am nil."

It's like (not exactly the same as)

var a *int
var b **int = &b

b isn't nil, biu it points to a pointer that /is/ nil.

Chris

--
Chris "allusive" Dollin

Sascha Matzke

unread,
Jan 20, 2012, 7:44:08 AM1/20/12
to golan...@googlegroups.com
Hi,

On Fri, Jan 20, 2012 at 13:06, Jan Mercl <jan....@nic.cz> wrote:
> if p, ok := se.(*Counter); ok && p != nil { ts := p.value.TimeSeries() }

Hmmm... Seems complicated.

What should I do if I don't know the concrete type (I have several
types implementing the specific interface here)?

Dmitry Vyukov

unread,
Jan 20, 2012, 7:48:42 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
On Fri, Jan 20, 2012 at 4:44 PM, Sascha Matzke <sascha...@didolo.org> wrote:
Hi,

On Fri, Jan 20, 2012 at 13:06, Jan Mercl <jan....@nic.cz> wrote:
> if p, ok := se.(*Counter); ok && p != nil { ts := p.value.TimeSeries() }

Hmmm... Seems complicated.

What should I do if I don't know the concrete type (I have several
types implementing the specific interface here)?

Perhaps just don't assign nils in the first place.

chris dollin

unread,
Jan 20, 2012, 7:49:35 AM1/20/12
to Sascha Matzke, golan...@googlegroups.com
On 20 January 2012 12:44, Sascha Matzke <sascha...@didolo.org> wrote:
> Hi,
>
> On Fri, Jan 20, 2012 at 13:06, Jan Mercl <jan....@nic.cz> wrote:
>> if p, ok := se.(*Counter); ok && p != nil { ts := p.value.TimeSeries() }
>
> Hmmm... Seems complicated.
>
> What should I do if I don't know the concrete type (I have several
> types implementing the specific interface here)?

Assign nil, not a nil pointer, to se.value.

Reply all
Reply to author
Forward
0 new messages