I found the comments of `findObject` in the runtime source: ```go // findObject returns the base address for the heap object **containing** // the address p, the object's span, and the index of the object in s. // If p does not point into a heap object, it returns base == 0. // // If p points is an invalid heap pointer and debug.invalidptr != 0, // findObject panics. // // refBase and refOff optionally give the base address of the object // in which the pointer p was found and the byte offset at which it // was found. These are used for error reporting. // // It is nosplit so it is safe for p to be a pointer to the current goroutine's stack. // Since p is a uintptr, it would not be adjusted if the stack were to move. //go:nosplit func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex uintptr) ```
On Sunday, February 6, 2022 at 10:33:35 AM UTC+8 rmfr wrote: > It suddenly occurred to me that it was very like `re-slice` —— as long as > part of the underlying array is referenced, the whole underlying array is > never gc-ed. I guess there is a method in gc which could locate the whole > underlying array as long as one address inside the array's address interval > was provided? So now I tend to believe that `Element1` is correct too, and > the `underlyBuf` filed in `Element2` is redundant and is not quite > necessary, am I correct? > > On Sunday, February 6, 2022 at 10:08:06 AM UTC+8 rmfr wrote: > >> Please take a look at the following code: >> >> ```go >> package main >> >> import ( >> "fmt" >> "runtime" >> "unsafe" >> ) >> >> func assert(b bool) { >> if b { >> } else { >> panic("unexpected") >> } >> } >> >> type Elementer interface { >> GetInt64Slice() []int64 >> GetByteSlice() []byte >> String() string >> } >> >> type Element1 struct { >> int64s []int64 >> bs []byte >> } >> >> func newElement1(int64Sz, bsSz int) *Element1 { >> assert(int64Sz > 0 && bsSz > 0) >> len0 := int64Sz * 8 >> len1 := bsSz >> buf := make([]byte, len0+len1) >> for i := range buf { >> buf[i] = byte(i) >> } >> e := &Element1{ >> int64s: unsafe.Slice((*int64)(unsafe.Pointer(&buf[0])), int64Sz), >> bs: unsafe.Slice((*byte)(&buf[len0]), bsSz), >> } >> return e >> } >> >> func (e *Element1) GetInt64Slice() []int64 { >> return e.int64s >> } >> >> func (e *Element1) GetByteSlice() []byte { >> return e.bs >> } >> >> func (e *Element1) String() string { >> return fmt.Sprintf("Element1:[% x % x]", e.GetInt64Slice(), >> e.GetByteSlice()) >> } >> >> type Element2 struct { >> underlyBuf []byte // <- is this field needed? >> int64s []int64 >> bs []byte >> } >> >> func newElement2(int64Sz, bsSz int) *Element2 { >> assert(int64Sz > 0 && bsSz > 0) >> len0 := int64Sz * 8 >> len1 := bsSz >> buf := make([]byte, len0+len1) >> for i := range buf { >> buf[i] = byte(i) >> } >> e := &Element2{ >> underlyBuf: buf, // <- >> int64s: unsafe.Slice((*int64)(unsafe.Pointer(&buf[0])), >> int64Sz), >> bs: unsafe.Slice((*byte)(&buf[len0]), bsSz), >> } >> return e >> } >> >> func (e *Element2) GetInt64Slice() []int64 { >> runtime.KeepAlive(e.underlyBuf) >> return e.int64s >> } >> >> func (e *Element2) GetByteSlice() []byte { >> runtime.KeepAlive(e.underlyBuf) >> return e.bs >> } >> >> func (e *Element2) String() string { >> runtime.KeepAlive(e.underlyBuf) >> return fmt.Sprintf("Element2:[% x % x]", e.GetInt64Slice(), >> e.GetByteSlice()) >> } >> >> func main() { >> var e Elementer >> fmt.Println("print with host endian:") >> e = newElement1(2, 4) >> fmt.Println("hi", e) >> e = newElement2(2, 4) >> fmt.Println("hi", e) >> } >> ``` >> >> And which yields: >> >> ``` >> hi Element1:[[ 706050403020100 f0e0d0c0b0a0908] 10 11 12 13] >> hi Element2:[[ 706050403020100 f0e0d0c0b0a0908] 10 11 12 13] >> ``` >> >> I'm not sure whether the `underlyBuf` filed in `Element2` is needed or >> not. When I'm reading the doc from ` >> https://pkg.go.dev/reflect#SliceHeader` >> <https://pkg.go.dev/reflect#SliceHeader> there is: >> >> > Moreover, the Data field is not sufficient to guarantee the data it >> references will not be garbage collected, so programs must keep a separate, >> correctly typed pointer to the underlying data. >> >> But in `https://pkg.go.dev/unsafe#Slice` >> <https://pkg.go.dev/unsafe#Slice> there are no such comments. So the >> question: >> >> Which implementation of `Elementer` is correct? `Element2` or both of >> them? >> >> Thanks a lot for your help. >> > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/907d7b7f-303b-4f1f-a3ee-b51563ebdeb6n%40googlegroups.com.