-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
unsafe docs and SliceHeader: I am not sure what is defined here #33794
Comments
In general using You don't need asUint16 := (*[1<<29]uint16)(unsafe.Pointer(obj.Ptr))[:obj.len:obj.len] The temporary conversion to a pointer to a very large array is harmless as we immediately the array pointer into a slice of the desired length. |
Ah-hah! That's the thing I was missing -- not just that the pointer could be freed, but that the pointer could become invalidated. I have been distrustful of the "very large array" idiom because in theory that means that the subexpression before the slice expression is possibly-invalid, although i suppose if the compiler is trusted not to actually try to build the object before continuing on to slicing it, it's harmless. It still bugs me in that it seems semantically-wrong. |
Note that it's a pointer to an array. There is no actual array value at any point. What we're doing is turning an So while the construct is certainly sketchy, and can fail on a 64-bit system if the underlying array is unreasonably large, it doesn't rely on trusting the compiler. The meaning is clearly defined by the language spec. |
Oh! I have seen that idiom before dereferencing the array before slicing. I hadn't realized you could do it without the dereference. Thanks! That's really neat. |
What version of Go are you using (
go version
)?1.12, but N/A
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?N/A
What did you do?
Read the documentation for
unsafe
.What did you expect to see?
Something that did not confuse me.
What did you see instead?
Something that confused me.
This has an accompanying example:
What's not obvious to me: Is the only reason this is "INVALID" that p might already be lost, such that a
runtime.KeepAlive(p)
after the last line would have saved it? Or is this also intended to cover the possibility that some future version of Go may have additional unspecified magic in a slice object which is not in theSliceHeader
parts, such that simply creating a SliceHeader (or a StringHeader) doesn't actually make a thing which could be a valid object?I've been writing code which has a pointer (which is persistent, and in a data structure which survives past the current scope, thus at no risk of being garbage collected), and which does something to the effect of:
In fact, obj.ptr isn't going away, so I'm not worried about garbage collection. But if an actual Slice were not exactly the same size as a SliceHeader, but rather, the SliceHeader were just a prefix of the actual internal slice representation... This code would in fact be just plain wrong, because other code might try to access the "rest" of the slice object, and not find it.
Instead, I'd need to do something like:
Which is, I suppose, certainly no harder to read, but I'm not sure whether it offers any semantic difference, apart from
u
holding the reference to the pointer, in a way that a temporary slice header object wouldn't.(Related-ish: #20171, #19367.)
The text was updated successfully, but these errors were encountered: