is //go:nosplit needed to avoid GC corruption above this pointer arithmetic function?

397 views
Skip to first unread message

Jason E. Aten

unread,
Oct 20, 2015, 7:03:05 PM10/20/15
to golang-nuts
I'm interfacing Go code with a large existing C codebase, and here I must do pointer arithmetic using unsafe.Pointer. 

I see in the following stackoverflow the comment that //go:nosplit should be used above the function definition to avoid garbage-collector corruption:

http://stackoverflow.com/questions/32700999/pointer-arithmetic-in-go  

  and see the example in the playgound

https://play.golang.org/p/RyGH-kpogP

Can somebody elaborate on when and whether //go:nosplit is necessary?

I certainly don't want to corrupt the GC, but I can't avoid the pointer arithmetic and I don't understand the concern/danger. How would //go:nosplit would avoid corruption?

Thank you!

Brad Fitzpatrick

unread,
Oct 20, 2015, 7:14:13 PM10/20/15
to Jason E. Aten, golang-nuts
Ian replied to the stackoverflow post.

But also: //go:nosplit is not part of the language. Unless you're working on the Go runtime itself, you shouldn't even use it, if even does anything outside of the core. It's probably just a comment if you try to use it.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ian Lance Taylor

unread,
Oct 20, 2015, 7:14:35 PM10/20/15
to Jason E. Aten, golang-nuts
On Tue, Oct 20, 2015 at 3:56 PM, Jason E. Aten <j.e....@gmail.com> wrote:
I don't think the comment on Stack Overflow is correct, and I just
added a comment of my own. A //go:nosplit comment doesn't make any
difference here.

The issue for documenting when it is safe to convert between
unsafe.Pointer and uintptr is https://golang.org/issue/8994 . In
practice, at present, it is safe to convert from unsafe.Pointer and
uintptr as long as you convert back in the same expression. That is,
it is safe to do this: unsafe.Pointer(uintptr(p) + o). //go:nosplit
has nothing to do with this. At some point I hope that we will pin
down the documentation on these conversions.

All that said, you can often convert a C pointer to a Go slice. To
convert from a C pointer p to type T where there are n valid elements,
write (*[0x7fffffff]T)(p)[0:n:n]. That will give you a []T of len n
where the backing array of the slice points to the C data (assuming
there are fewer than 0x7fffffff elements in the array). That is a lot
safer and easier to work with than doing pointer arithmetic.

Ian

Jason E. Aten

unread,
Oct 20, 2015, 11:13:17 PM10/20/15
to golang-nuts
Thanks guys.

Sokolov Yura

unread,
Oct 21, 2015, 2:15:05 AM10/21/15
to golang-nuts
Accordingly to mentioned github issue, reflect.Value.Pointer() is useless.

So, it were made to return uintptr to demand more safety from programmer, and now it becomes unsafe/broken itself.

Is there way to fix it?

Sokolov Yura

unread,
Oct 21, 2015, 2:18:16 AM10/21/15
to golang-nuts
For example : could GC treat uintptr amd intptr types as pointers?

Ian Lance Taylor

unread,
Oct 21, 2015, 10:23:15 AM10/21/15
to Sokolov Yura, golang-nuts
On Tue, Oct 20, 2015 at 11:18 PM, Sokolov Yura <funny....@gmail.com> wrote:
> For example : could GC treat uintptr amd intptr types as pointers?

No, because there are many uintptr values that are not pointers. The
GC needs to know exactly what is a pointer and what is not. It can't
work with values that might or might not be pointers. Specificaly,
when copying a stack, we need to adjust all pointers that point into
the stack. If a uintptr value holds an integer that coincidentally
looks like a stack address, it would be a disaster if we changed it.

Ian

Sokolov Yura

unread,
Oct 21, 2015, 11:29:55 AM10/21/15
to golang-nuts
Then there is should other way to fix it.

btw, i think this bug already breaks backward compatibility promise, cause it may break programs which uses such construction.

Ian Lance Taylor

unread,
Oct 21, 2015, 1:58:31 PM10/21/15
to Sokolov Yura, golang-nuts
On Wed, Oct 21, 2015 at 8:29 AM, Sokolov Yura <funny....@gmail.com> wrote:
> Then there is should other way to fix it.

I'm sorry, I'm not sure what you mean. Can you give an example?

> btw, i think this bug already breaks backward compatibility promise, cause it may break programs which uses such construction.

The backward compatibility promise explicitly does not apply to
packages that import unsafe. It can't, because a package that imports
unsafe can do anything. Requiring a program that works today using
unsafe to always work in the future would be too much of a restriction
on the implementation. For example, it would have prevented us from
changing from split stacks to copying stacks.

Ian
Reply all
Reply to author
Forward
0 new messages