Go lacked pointer arithmetic for a reason, so it's ok to be very verbose when using them.
(they are highly discouraged anyway.)
You should probably look at what go vet already diagnoses for Go 1.3.That's what I personally believe the rules are.
The only difference I see at a quick glance is that go vet allowsunsafe.Pointer(uintptr(p)+n)where you are proposing a different spellingunsafe.Add(p, n)The new spelling is clearer but requiring it invalidates lots of old code. Using the old spelling reduces fragmentation and is otherwise equivalent.
I'm also proposing stricter semantics that a pointer into a Go variable can only be derived from other pointers into the same Go variable, and that the runtime provide instrumentation to check for that. Implementing that would be somewhat easier under the new spelling, but it could be made to work under the old spelling as well.
On Mon, Aug 11, 2014 at 1:52 PM, Russ Cox <r...@golang.org> wrote:
You should probably look at what go vet already diagnoses for Go 1.3.That's what I personally believe the rules are.I looked at it a little bit, but I notice it didn't catch this code from src/pkg/syscall/sockcmsg_unix.go that I would think is erroneous:data := uintptr(cmsgData(h))for _, fd := range fds {*(*int32)(unsafe.Pointer(data)) = int32(fd)data += 4}Even if I add a runtime.GC() call within the loop body (which I would think would certainly risk invalidating "data"), "go vet" doesn't complain.Would you argue that's a bug in "go vet" or that I misunderstand and a Go implementation is required to ensure the above code runs as intended?
The only difference I see at a quick glance is that go vet allowsunsafe.Pointer(uintptr(p)+n)where you are proposing a different spellingunsafe.Add(p, n)The new spelling is clearer but requiring it invalidates lots of old code. Using the old spelling reduces fragmentation and is otherwise equivalent.I'm also proposing stricter semantics that a pointer into a Go variable can only be derived from other pointers into the same Go variable,
and that the runtime provide instrumentation to check for that. Implementing that would be somewhat easier under the new spelling, but it could be made to work under the old spelling as well.
Additionally, I think the new spelling gives some confidence to users that code likeunsafe.Add(f(), g())will work as intended, whereasunsafe.Pointer(uintptr(f()) + g())
it's a difference of go vet specifying all package files versus go tool vet pkg/syscallprobably a cmd/go bug?
I don't believe so.
% go vet syscall
go/src/pkg/syscall/sockcmsg_unix.go:82: possible misuse of unsafe.Pointer
exit status 1
% go tool vet go/src/pkg/syscall
go/src/pkg/syscall/sockcmsg_unix.go:82: possible misuse of unsafe.Pointer
%
--
On Aug 17, 2014 1:01 AM, "Keith Randall" <k...@google.com> wrote:
> > The only difference I see at a quick glance is that go vet allows
> > unsafe.Pointer(uintptr(p)+n)
> > where you are proposing a different spelling
> > unsafe.Add(p, n)
>
> I'm partial toward adding a method to unsafe.Pointer so you can do
> p.Add(n)
this had been proposed before, and i think the answer was always we won't add methods to built-in types.
the semantic is also a problem: should p.Add change p?
> (or p.Offset(n) or p.Adjust(n)?) which does the equivalent thing. In any case, I agree with Matthew that having a way to move an unsafe.Pointer without converting to uintptr and back would be nice long term. We couldn't deprecate the old way for a while, of course.
i don't understand why the old form isn't ok in the long term: as long as the operation itself is safe (adjusted p still points to the same object), p should keep the object alive and
during pointer manipulation it isn't a safe point for GC and object movement. (the compiler need to do pointer arithmetic under the hood, so it needs a way to control GC involvement when the pointer is only contained in registers anyway)
i think i understand why you want this: the runtime uses a lot of unsafe. but still i don't support any proposal that make pointer arithmetic easier to write. that feature should be strongly discouraged instead.
On Aug 17, 2014 1:01 AM, "Keith Randall" <k...@google.com> wrote:
> > The only difference I see at a quick glance is that go vet allows
> > unsafe.Pointer(uintptr(p)+n)
> > where you are proposing a different spelling
> > unsafe.Add(p, n)
>
> I'm partial toward adding a method to unsafe.Pointer so you can do
> p.Add(n)
this had been proposed before, and i think the answer was always we won't add methods to built-in types.the semantic is also a problem: should p.Add change p?
> (or p.Offset(n) or p.Adjust(n)?) which does the equivalent thing. In any case, I agree with Matthew that having a way to move an unsafe.Pointer without converting to uintptr and back would be nice long term. We couldn't deprecate the old way for a while, of course.
i don't understand why the old form isn't ok in the long term: as long as the operation itself is safe (adjusted p still points to the same object), p should keep the object alive and
during pointer manipulation it isn't a safe point for GC and object movement. (the compiler need to do pointer arithmetic under the hood, so it needs a way to control GC involvement when the pointer is only contained in registers anyway)i think i understand why you want this: the runtime uses a lot of unsafe. but still i don't support any proposal that make pointer arithmetic easier to write. that feature should be strongly discouraged instead.
i think i understand why you want this: the runtime uses a lot of unsafe. but still i don't support any proposal that make pointer arithmetic easier to write. that feature should be strongly discouraged instead.
If the memory for a value is moved while it's address is stored in a uintptr, the uintptr isn't updated. In the future this might happen with heap objects in a compacting GC, in the present it can happen with stack objects due to contiguous stacks. http://play.golang.org/p/v-NlS3AS9B
Currently to be safe with pointers to stack objects, you need to ensure there are no function calls between the conversion to uintptr, the addition of the offset, and the conversion back to unsafe.Pointer/the original pointer type. In the future, to protect heap pointers from the compacting GC, you need to prevent the GC stop the world from happening in between the three stages, ie: no channel operations, no allocations, as well as no function calls.
For me it isn't about making pointer arithmetic easier, it's about preventing races between the code that needs to perform the arithmetic, and the code that can change the location of objects. If it's possible to (somehow) apply offsets directly to unsafe.Pointers, then the detour though uintptr is not necessary, so the object moving code will always update the pointers correctly, and there is never a point in the code where you are depending on the compaction or stack moving to not happen.