That's very good to know. Thanks, Ian.

Unfortunately if I use this KeepAlive-based fix, p escapes and so the
function now allocates. I guess I'll stick with the original version
from my first email.

Does this indicate a shortcoming of either compiler support for
KeepAlive or escape analysis in general?

Caleb

On Thu, Mar 23, 2017 at 10:26 AM, Ian Lance Taylor <i...@golang.org> wrote:
> On Thu, Mar 23, 2017 at 9:16 AM, Caleb Spare <cesp...@gmail.com> wrote:
>>
>> Brief follow-up: does the seeming validity of the code rely at all on
>> the fact that the indicated line is written as a single line? What if,
>> instead, a *StringHeader var were extracted?
>>
>> func stringToSliceUnsafe(s string) []uint64 {
>>         var v []uint64
>>         h := (*reflect.StringHeader)(unsafe.Pointer(&s)) // <--
>>         sh := (*reflect.SliceHeader)(unsafe.Pointer(&v))
>>         sh.Data = h.Data
>>         sh.Len = h.Len >> 3
>>         sh.Cap = h.Len >> 3
>>         return v
>> }
>>
>> (Play link: https://play.golang.org/p/BmGtYTsGNY)
>>
>> Does h keep s alive? A strict reading of rule 6 doesn't seem to say
>> that keeping a *StringHeader or *SliceHeader around keeps the
>> underlying string/slice alive (but it's sort of implied by the rule 6
>> example code, which doesn't refer to s after converting it to a
>> *StringHeader).
>
> That is an interesting point.  I don't think there is anything keeping
> s alive here.  I think this isn't quite the same as the example in the
> docs, because that example is assuming that you are doing to use s
> after setting the fields--why else would you be doing that?  In this
> case it does seem theoretically possible that s could be freed between
> the assignment to h and the use of h.Data.  With the current and
> foreseeable toolchains it's a purely theoretical problem, since there
> is no point there where the goroutine could be preempted and the fact
> that s is no longer referenced be detected.  But as a theoretical
> problem it does seem real.  One fix would be something like
>     p := &s
>     h := (*reflect.StringHeader)(unsafe.Pointer(p))
>     sh := (*reflect.SliceHeader)(unsafe.Pointer(&v))
>     sh.Data = h.Data
>     sh.Len = ...
>     sh.Cap = ...
>     runtime.KeepAlive(p)
>
> Ian

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to