Ah, of course, silly me conflating alignment with allocation size.  Thanks 
for the suggestion.

Best,
Bill

On Monday, February 27, 2017 at 3:35:32 PM UTC-5, Ian Lance Taylor wrote:
>
> On Mon, Feb 27, 2017 at 11:57 AM, Bill Katz <[email protected] 
> <javascript:>> wrote: 
> > I thought that's handled by the inhdr.Cap % 8 == 0 check.  Isn't 
> inhdr.Data 
> > essentially a pointer into memory with inhdr.Cap showing the size of the 
> > allocated region? 
>
> Yes, but that is not sufficient.  Consider 
>     b := make([]byte, 9) 
>     u, err := byteToUint64(b[1:]) 
> Here the len and cap of b are 8, but the data field will not be aligned. 
>
> I think your code is safe but there is a simpler way to do it: 
>
>     if len(b) % 8 != 0 || cap(b) % 8 != 0 || 
> uintptr(unsafe.Pointer(&b[0])) % 8  != 0 { 
>         return errors.New("bad len or cap or alignment") 
>     } 
>     return (*[1<<27]uint64)(unsafe.Pointer(&b[0]))[:len(b)/8:cap(b)/8] 
>
> Ian 
>
> > On Monday, February 27, 2017 at 2:14:46 PM UTC-5, xingtao zhao wrote: 
> >> 
> >> I think you need to check if inhdr.Data is aligned with 8 bytes as 
> well. 
> >> 
> >> On Sunday, February 26, 2017 at 2:54:00 PM UTC-8, Bill Katz wrote: 
> >>> 
> >>> Hi, 
> >>> 
> >>> We'd like to do a zero-copy conversion of []byte to []uint64 where the 
> >>> underlying memory for the byte slice is properly aligned for N uint64 
> >>> values.  After looking at (6) in the unsafe package documentation, I'm 
> >>> wondering if the code below is valid because I only use 
> reflect.SliceHeader 
> >>> as pointers, and it seems to fit pattern 6. 
> >>> 
> >>> https://play.golang.org/p/FxxKIK08pX 
> >>> 
> >>> package main 
> >>> 
> >>> import ( 
> >>> "fmt" 
> >>> "reflect" 
> >>> "unsafe" 
> >>> ) 
> >>> 
> >>> func byteToUint64(b []byte) (out []uint64, err error) { 
> >>> inhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&b)) 
> >>> if inhdr.Len % 8 != 0 { 
> >>> err = fmt.Errorf("cannot convert non-aligned []byte length (%d) to 
> >>> []uint64", inhdr.Len) 
> >>> return 
> >>> } 
> >>> if inhdr.Cap % 8 != 0 { 
> >>> err = fmt.Errorf("cannot convert non-aligned []byte capacity (%d) to 
> >>> []uint64", inhdr.Cap) 
> >>> return 
> >>> } 
> >>> outhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&out)) 
> >>> outhdr.Len = inhdr.Len / 8 
> >>> outhdr.Cap = inhdr.Cap / 8 
> >>> outhdr.Data = inhdr.Data 
> >>> out = *(*[]uint64)(unsafe.Pointer(&outhdr)) 
> >>> return 
> >>> } 
> >>> 
> >>> func main() { 
> >>> b := make([]byte, 24) 
> >>> u, err := byteToUint64(b) 
> >>> if err != nil { 
> >>> fmt.Println(err) 
> >>> } else { 
> >>> fmt.Printf("b: %v\n", b) 
> >>> fmt.Printf("u: %v\n", u) 
> >>> fmt.Printf("len(u) = %d, cap(u) = %d\n", len(u), cap(u)) 
> >>> u[0] = 15 
> >>> fmt.Printf("Set u[0] to 15\n") 
> >>> fmt.Printf("b: %v\n", b) 
> >>> fmt.Printf("u: %v\n", u) 
> >>> u[2] = 255 
> >>> fmt.Printf("Set u[2] to 255\n") 
> >>> fmt.Printf("b: %v\n", b) 
> >>> fmt.Printf("u: %v\n", u) 
> >>> } 
> >>> } 
> >>> 
> >>> Outputs: 
> >>> 
> >>> b: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 
> >>> u: [0 0 0] 
> >>> len(u) = 3, cap(u) = 3 
> >>> Set u[0] to 15 
> >>> b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 
> >>> u: [15 0 0] 
> >>> Set u[2] to 255 
> >>> b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0] 
> >>> u: [15 0 255] 
> >>> 
> >>> 
> > -- 
> > 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 [email protected] <javascript:>. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to