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

runtime: KeepAlive causes its argument to escape #19687

Closed
cespare opened this issue Mar 24, 2017 · 3 comments
Closed

runtime: KeepAlive causes its argument to escape #19687

cespare opened this issue Mar 24, 2017 · 3 comments

Comments

@cespare
Copy link
Contributor

cespare commented Mar 24, 2017

What version of Go are you using (go version)?

I see this on Go 1.8 and also tip. The examples below were run with tip.

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

linux/amd64

See original context here: https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/6yntq3OVBQAJ

It seems that calling runtime.KeepAlive causes the argument to escape:

package main

import "runtime"

func f(s string) {
	runtime.KeepAlive(s)
}

func main() {
	f("hello")
}

// ./test.go:5:6: can inline f
// ./test.go:9:6: can inline main
// ./test.go:10:3: inlining call to f
// ./test.go:6:19: s escapes to heap
// ./test.go:5:10: leaking param: s
// ./test.go:10:3: s escapes to heap

Bizarrely, if I change the definition of KeepAlive to give the parameter a name:

//go:noinline
func KeepAlive(v interface{}) {} // instead of func KeepAlive(interface{}) {}

then the argument doesn't escape:

package main

import "runtime"

func f(s string) {
	runtime.KeepAlive(s)
}

func main() {
	f("hello")
}

// ./test.go:5:6: can inline f
// ./test.go:9:6: can inline main
// ./test.go:10:3: inlining call to f
// ./test.go:5:10: f s does not escape
// ./test.go:6:19: f s does not escape
// ./test.go:10:3: main s does not escape

@randall77 @ianlancetaylor

@dmac
Copy link

dmac commented Mar 24, 2017

Here's a minimal example that I believe exhibits the same issue:

package main

//go:noinline
func foo(*int) {}

func main() {
	n := 1
	foo(&n)
}

// ./test.go:8: &n escapes to heap
// ./test.go:7: moved to heap: n
package main

//go:noinline
func foo(p *int) {}

func main() {
	n := 1
	foo(&n)
}

// ./test.go:4: foo p does not escape
// ./test.go:8: main &n does not escape

@bradfitz bradfitz added this to the Go1.9Maybe milestone Mar 24, 2017
@randall77 randall77 self-assigned this Mar 24, 2017
@josharian
Copy link
Contributor

cc @dr2chase

@gopherbot
Copy link

CL https://golang.org/cl/38600 mentions this issue.

@golang golang locked and limited conversation to collaborators Mar 24, 2018
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