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

Method parameters can also escape to the heap #21

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

fmstephe
Copy link

When this happens the 'go build -gcflags="-m"' output will write something like

offheap/internal/pointerstore/pointer_reference.go:96:7: leaking param: r

This means that the parameter, including the method receiver, escapes to the heap and cannot be stack allocated. Unfortunately it has different text from the usual "escapes to heap:" so it gets missed by gcassert.

Here we include an additional text check for noescape annotations and fail on leaking parameters too.

When this happens the 'go build -gcflags="-m"' output will write
something like

offheap/internal/pointerstore/pointer_reference.go:96:7: leaking param: r

This means that the parameter, including the method receiver, escapes to
the heap and cannot be stack allocated. Unfortunately it has different
text from the usual "escapes to heap:" so it gets missed by gcassert.

Here we include an additional text check for noescape annotations and
fail on leaking parameters too.
@fmstephe
Copy link
Author

For a real world example of this the DataPtr() method leaks the method handler to the heap. This is caused by the (quite subtle) allocation required because the method handler is passed into a fmt.Printf(...) call.

/~https://github.com/fmstephe/memorymanager/pull/10/files#diff-54bbdd0a1d99db9a7e8f33f480f72e4a54a4d5210a73c543bfc533c468920e5eL108

The commit I am linking too here is intended to cause the unintended allocation to happen, and I had expected it to cause my build to fail. But the build succeeded. So I looked deeper and realised that the text for method parameters was different from the escapes to heap that I, and gcassert, had expected.

@fmstephe
Copy link
Author

A very reasonable alternative approach here would be to introduce a separate assertion for method parameters. gcassert:noleak would work.

Personally I think just combining the two is ok. But, if you would prefer a new assertion I am happy to make a PR for that. Either way I will be using the assertions on method parameters extensively in my project so I would be very happy to find an acceptable solution for this.

Thanks :)

@fmstephe fmstephe force-pushed the handle-leaking-param-escapes branch from 33b961f to 07ae031 Compare January 17, 2025 11:53
@yuzefovich
Copy link
Collaborator

Thanks for the patch! It seems reasonable to me.

My colleague @mgartner did recently mention that "leaking" something doesn't always result in that something "escaping". Marcus, what do you think about this patch?

@fmstephe
Copy link
Author

I did wonder about this myself. As the wording change is likely deliberate and may have a different meaning. If it is meaningfully different then I think a separate annotation gcassert:noleak could be reasonable.

In the example I posted in my memorymanager project, that leaked parameter did result in a memory allocation per method call. So at least in this instance it behaved like I would expect an escaping variable to behave.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants