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

cmd/cgo: proposed #cgo noescape seems redundant #64857

Closed
eliasnaur opened this issue Dec 24, 2023 · 4 comments
Closed

cmd/cgo: proposed #cgo noescape seems redundant #64857

eliasnaur opened this issue Dec 24, 2023 · 4 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.

Comments

@eliasnaur
Copy link
Contributor

Go version

go1.22rc1

What operating system and processor architecture are you using (go env)?

N/A

What did you do?

The proposed #cgo noescape pragma (#56378) is documented to say:

When passing a Go pointer to a C function the compiler normally ensures
that the Go object lives on the heap. If the C function does not keep
a copy of the Go pointer, and never passes the Go pointer back to Go code,
then this is unnecessary. The #cgo noescape directive may be used to tell
the compiler that no Go pointers escape via the named C function.
If the noescape directive is used and the C function does not handle the
pointer safely, the program may crash or see memory corruption.

However, the property "If the C function does not keep a copy of the Go pointer" seems guaranteed for non-pinned memory by the rule that

C code may not keep a copy of a Go pointer after the call returns,
unless the memory it points to is pinned with [runtime.Pinner]

So my question is: what can "#cgo noescape" promise that is not already promised?

One answer may be "pinned objects may be retained by C". But then why not force objects passed to runtime.Pinner to the heap?

Another answer may be "Go objects may escape through callbacks to from C to Go", then that seems entirely covered by the "#cgo nocallback" pragma.

In summary, "#cgo noescape" seems to add no useful information.

What did you expect to see?

No "#cgo noescape" pragma, or clearer documentation what "#cgo noescape" promises that is not already promised.

What did you see instead?

A seemingly redundant "#cgo noescape" pragma.

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Dec 24, 2023
@Jorropo
Copy link
Member

Jorropo commented Dec 25, 2023

@eliasnaur I see a third case, C can return a Go pointer back to go.
Then the pointer does escape but isn't retained by C.

The escape analysis is able to model this properly when reading go code, but the noescape pragmas are way under capable compared to the level of detail the escape analysis read code.

@thanm
Copy link
Contributor

thanm commented Dec 28, 2023

Yes, I think (if my memory serves) the issue has to do with Go -> C -> Go cases. Doesn't happen very often, but it is something we support. Perhaps the documentation could be clarified/enhanced.

@doujiang24
Copy link
Contributor

@eliasnaur #cgo noescape is disabled in 1.22, and will enable in 1.23, so, there is no much doc about it.

For such a Go function:

func get() uint64 {
	var value C.uint64_t
	C.GetIntegerValue(&value)
	return uint64(value)
}

without #cgo noescape , value will always escape to heap.
after adding #cgo noescape GetIntegerValue, value will be on stack.
it's a normal optimization for cgo.

And pin is another thing.
we can also say the Go pointer &value is pinned, when it's on the stack, since it won't move before C entering Go again.

@eliasnaur
Copy link
Contributor Author

Yes, I think (if my memory serves) the issue has to do with Go -> C -> Go cases. Doesn't happen very often, but it is something we support. Perhaps the documentation could be clarified/enhanced.

Thank you. I missed that a returned value is a violation of "never passes the Go pointer back to Go code".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.
Projects
None yet
Development

No branches or pull requests

5 participants