No panic on nil pointer dereference

583 views
Skip to first unread message

Nate Finch

unread,
Jan 9, 2013, 2:20:22 PM1/9/13
to golan...@googlegroups.com
Saw an interesting thing on the Go+ Google+ group.... if you have a struct with no fields, the compiler won't panic on dereferencing a nil pointer to the struct (at least in the playground):


I suppose this is just a compiler optimization, since there's no actual data behind the pointer, but I found it surprising.

Kyle Lemons

unread,
Jan 9, 2013, 2:26:23 PM1/9/13
to Nate Finch, golang-nuts
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x400c1e]

It panics for me.


--
 
 

Nate Finch

unread,
Jan 9, 2013, 2:28:29 PM1/9/13
to golan...@googlegroups.com, Nate Finch
Sorry, you have to comment out the Name field to avoid the panic.  I should have linked to the version that does not panic:

bryanturley

unread,
Jan 9, 2013, 2:29:22 PM1/9/13
to golan...@googlegroups.com

func (x *Y) A(z int) { }

gets automagically turned into

func A(x *Y, z int) { }

I don't think it is a compiler optimization it is just you not using x.

 

Jan Mercl

unread,
Jan 9, 2013, 2:29:33 PM1/9/13
to Nate Finch, golang-nuts

minux

unread,
Jan 9, 2013, 2:38:21 PM1/9/13
to Nate Finch, golan...@googlegroups.com
This is consistent with the function argument case: http://play.golang.org/p/pLOC0fuho7

As discussed today, zero-sized struct behave really like zero-sized object, that is,
you can get a pointer to them (although all those pointer could be equal), but when
when passing them by value, the receiver won't take any value (because there is none)
so there really isn't any differences between a nil pointer to a zero-sized object and
any other pointer to the same kind of object.

or put it another way, what do you expect from dereferencing a pointer to a zero-sized
object? (you can't even access the bit located at that address because 1 bit is bigger
than 0, so this will be effectively accessing an out-of-bound pointer)

Peter

unread,
Jan 9, 2013, 2:41:22 PM1/9/13
to golan...@googlegroups.com, Nate Finch
An example without methods:

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

minux

unread,
Jan 9, 2013, 2:44:55 PM1/9/13
to Jan Mercl, Nate Finch, golang-nuts
i disagree.

let's consider this minimum case: http://play.golang.org/p/JcXbDAaqKP
as explained in my previous post, the compiler is not allowed to dereference the pointer
because if it (tries to) get any non-zero-sized data from that, you will be accessing out
of bound. However, getting zero-sized data means not dereference operation at all, thus
it won't trigger the panic.

in other words, if type Foo is zero sized, then any pointer to Foo should be considered
equal (the spec explicitly states that all pointers to Foo could all be equal).

Peter

unread,
Jan 9, 2013, 2:58:31 PM1/9/13
to golan...@googlegroups.com, Jan Mercl, Nate Finch
Equal, but nil?

If x is nil, an attempt to evaluate *x will cause a run-time panic. 

David DENG

unread,
Jan 9, 2013, 9:46:03 PM1/9/13
to golan...@googlegroups.com
Maybe only when you access the fields (or copy the struct), illegal accessing signal from the OS occurs, and then translated into an error.

I just guess.

David

steve wang

unread,
Jan 9, 2013, 10:42:48 PM1/9/13
to golan...@googlegroups.com, Jan Mercl, Nate Finch
This behavior will lead to the outcome that my programm works fine untile I add a field into a struct someday. 
It soulds quite weird.
My program crashs just because I added a field into a struct?

Johann Höchtl

unread,
Jan 10, 2013, 3:58:51 AM1/10/13
to golan...@googlegroups.com


Am Donnerstag, 10. Januar 2013 03:46:03 UTC+1 schrieb David DENG:
Maybe only when you access the fields (or copy the struct), illegal accessing signal from the OS occurs, and then translated into an error.

I think the underlying problem is that instances of size 0 are valid as here:
http://play.golang.org/

C doesn't allow instances of size 0:
http://ideone.com/JTLUM8

but clearly void* which may later be casted to sthg. concrete (and emulate  polymorphism but also cause the plague)

minux

unread,
Jan 10, 2013, 4:50:51 AM1/10/13
to steve wang, golan...@googlegroups.com, Jan Mercl, Nate Finch
How often do you add a field to an empty struct?
and how often do you do that when the code dealing with the struct{} is already done?

In fact, I can't think of a reason to do this: write code dealing with a struct{} first, and then
start filling the struct with fields.

steve wang

unread,
Jan 10, 2013, 6:10:17 AM1/10/13
to golan...@googlegroups.com, steve wang, Jan Mercl, Nate Finch
It's possible that there may be some empty structs which just exist for the implementation of some interfaces.
And someday the programmer wants to add some fields into some of those empty structs and then he will get a surprising panic.

Nate Finch

unread,
Jan 10, 2013, 7:08:53 AM1/10/13
to golan...@googlegroups.com, steve wang, Jan Mercl, Nate Finch
Yeah, sorry, Minux, but I have to agree with Steve here. Having inconsistent behavior for nil pointers is just asking for trouble. It doesn't really matter how often the situation would happen - it's just not a good idea. The difference between "causes a panic" and "doesn't cause a panic" is huge enough to outweigh the rarity of the situation.

I'm not an experienced go programmer, but I can already think of a few ways this could happen:
  • If you're mocking out an interface as a noop, either for testing or for use in a library where you just don't care about that part of the functionality, and then plans change and you decide you do want to store some data (e.g. recording number of times methods are called in the testing object, or implementing just a little of the functionality).
  • If you made a wrapper object that forwards calls to a singleton service, and then you just decide to embed an instance of the service object later so it can be more easily tested with a mock.
  • Pretty much anytime you have an empty struct.... 
Code changes all the time, and often times not by the person who wrote it in the first place.

Now, this is not to say that it's an easy fix. I understand that zero length data structures make things problematic for the compiler - I read that other thread about it. But I think it's pretty import to have a nil pointer always panic, regardless of what it's pointing to.

-Nate

Peter

unread,
Jan 10, 2013, 11:41:10 AM1/10/13
to golan...@googlegroups.com, steve wang, Jan Mercl, Nate Finch
I don't think the current behaviour fits in with the spec. Regardless of the type of nil pointer, and the special memory considerations of empty structs, its behaviour should surely be the same?

Minux, does your reading of the spec suggest otherwise?

Jan, is this the same issue? It doesn't involve methods.

My most minimal example: http://play.golang.org/p/6PROWcnMKB

Jan Mercl

unread,
Jan 11, 2013, 3:53:09 AM1/11/13
to Peter, golang-nuts, steve wang, Nate Finch
On Thu, Jan 10, 2013 at 5:41 PM, Peter <peter.a...@gmail.com> wrote:
> I don't think the current behaviour fits in with the spec. Regardless of the
> type of nil pointer, and the special memory considerations of empty structs,
> its behaviour should surely be the same?
>
> Minux, does your reading of the spec suggest otherwise?
>
> Jan, is this the same issue? It doesn't involve methods.
>
> My most minimal example: http://play.golang.org/p/6PROWcnMKB

Yes, I think it's the same issue. IMO: The simple and general rule is
that dereferencing a nil pointer _anywhere_ _must_ panic (per specs, I
hope). The current behavior is a compiler bug AFAICS.

-j

Nate Finch

unread,
Jan 11, 2013, 8:50:17 AM1/11/13
to golan...@googlegroups.com, Peter, steve wang, Nate Finch
It does look like there's an issue already submitted for this, btw:
Reply all
Reply to author
Forward
0 new messages