Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec: If x is of pointer and has the value nil calling x.f DOES NOT cause a run-time panic #4464

Closed
gopherbot opened this issue Nov 29, 2012 · 11 comments

Comments

@gopherbot
Copy link

by eric.atienza@mydoceapower.com:

What steps will reproduce the problem?
@see http://play.golang.org/p/unO74If5mD


What is the expected output?
in the expression "a.b.c.Check()" a is not nil, but b is. 
I expect a run time panic to occur:

"If x is of pointer or interface type and has the value nil, assigning to,
evaluating, or calling x.f causes a run-time panic." (spec extract)


What do you see instead?
the method Check() is called instead.

Which compiler are you using?  6g
Which operating system are you using? Linux 3.5.0-18-generic
Which version are you using?  (run 'go version')1.0.3
@ianlancetaylor
Copy link
Contributor

Comment 1:

The spec appears to be incorrect here.  The language permits you to call a pointer
method with a nil pointer.

Labels changed: added priority-soon, documentation, removed priority-triage.

Owner changed to @griesemer.

@gopherbot
Copy link
Author

Comment 2 by eric.atienza@mydoceapower.com:

I've updated the example here http://play.golang.org/p/lzQAC_j7Oy
What you said is that it's correct to call a method on a nil pointer. Agreed, this would
be a.b.Check()
but here what we've got is a.b.c.Check() where b (in the middle) is nil.
in the Check method, the receiver address is 0x0c ( apparently offset of c in B struct),
obviously not nil. There is no way to check that this address is correct (any attempt to
dereference it leads to a panic)

@rsc
Copy link
Contributor

rsc commented Nov 29, 2012

Comment 3:

Thank you for this example. This is terrible. We may need to rethink
how the semantics here.

@ianlancetaylor
Copy link
Contributor

Comment 4:

I think we still need to adjust the spec, but now that I see what is going on I agree
that this example ought to panic.  We may need to add an explicit nil check to every
automatic pointer field dereference when calling a method.

Labels changed: added compilerbug.

@rsc
Copy link
Contributor

rsc commented Nov 29, 2012

Comment 5:

Yes but it's also not just methods:
type T struct { x, y int }
var t *T
p := &t.y
What do we say about p here? Right now p is 4, so it is != nil yet
dereferencing it crashes. That's a class of pointer I don't think we
intended to expose.

@griesemer
Copy link
Contributor

Comment 6:

I think there are two approaches:
1) do early checks; i.e., possibly add an extra instruction to cause a nil-panic if
necessary
2) do late checks; i.e., only if a value pointed to via a pointer is actually _used_
(this may still require early checks because of offsets that are greater than 4K or
whatever the page size)
Either way requires some adjustments in the spec. Sigh.

@rsc
Copy link
Contributor

rsc commented Nov 29, 2012

Comment 7:

The problem with 'late checks' is that they cannot be programmed around.
It is easy to write code that avoids dereferencing nil.
It is nearly impossible to write code that avoids dereferencing 4
(from the last example).
I think we'll need to do something more like 'early checks' (although
defining exactly what is checked is tricky) and then the compiler will
be free to omit checks that it can prove don't change the semantics.
For example
    x = t.y
doesn't need to explicitly check t for nil because the t.y read will fault.
But perhaps
    x = &t.y
does need to check t for nil.
Not saying that for sure, but it's a possibility.

@remyoudompheng
Copy link
Contributor

Comment 8:

this discussion duplicates issue #4238.

@cznic
Copy link
Contributor

cznic commented Nov 30, 2012

Comment 9:

It seems to me that checking (explicitly, in code) pointers for being nil is still not
necessary (assuming that's being caught by a signal). Instead, I think the "bad" case
can be reduced to checking for (explicitly, in code at run time) the pointer arithmetic
`p` operand to be non zero while/whenever computing `p+field_offset`, where p ==
&some_struct_instance.

@rsc
Copy link
Contributor

rsc commented Dec 10, 2012

Comment 10:

Status changed to Duplicate.

Merged into issue #4238.

@rsc
Copy link
Contributor

rsc commented Dec 10, 2012

Comment 11:

Labels changed: added size-xl.

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1 label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants