On Tue, May 8, 2018 at 12:51 PM, <[email protected]> wrote: > > On Tuesday, May 1, 2018 at 10:15:08 PM UTC+2, Ian Lance Taylor wrote: >> >> On Tue, May 1, 2018 at 1:00 PM, <[email protected]> wrote: >> > >> > I looked at the source but can't understand it well enough. >> > >> > If I allocate a [1000]byte, or a []byte, I understand the GC will need >> > to >> > mark the slice/array itself for collection. However, does the GC mark >> > all >> > the bytes within, and does the marking phase attempt to follow all the >> > items? >> >> A [1000]byte value holds no pointers, so the GC marks that value once >> and does not look inside it. >> >> A []byte holds a single pointer, to the backing array, and the backing >> array holds no pointers, so the GC marks the []byte and the backing >> array, and then stops. >> >> > > Interesting. And what happens in this case: > > type Foo struct { > s string > } > > func makeFoo() *Foo { > buf := make([]byte,16) > foo := (*Foo)(unsafe.Pointer(&buf)) > foo.s = "Hello World!" > return foo > } > > If I understand you correctly, the GC would consider the string "Hello > World!" to be collectable, because its only pointer is in memory that should > not hold pointers. Or does the assignment of foo.s add some mark to the > memory block that it now may contain pointers?
That program is not one of the valid unsafe.Pointer patterns documented at https://golang.org/pkg/unsafe, so it is invalid. As you say, the string "Hello World!" could be collected by the GC. With the current implementations the string is likely to be in read-only memory so it would not be collected, but of course future implementations may act differently. In the current implementations the assignment to foo.s does not add any marking to the memory block. It would remain marked as not containing any pointers. > If I changed buf to > > buf := make([]unsafe.Pointer,16) > > would that make things work? Now the GC knows that buf may contain pointers > and if I understand correctly it doesn't need to know the type of pointer. That would still be invalid according to the unsafe.Pointer docs. The results would be different. The representation of a string is both a pointer and a length. With this change, you would be storing the length into a field marked as containing a pointer. In other words, you would have an invalid pointer value. The most likely result would be a crash when the garbage collector tried to mark the memory to which that pointer points. 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
