Ah reflect.StructOf! I totally missed that, that was the missing piece. Thanks for the detailed response Ian, much appreciated.
Tibor On Friday, August 18, 2023 at 11:06:27 PM UTC+2 Ian Lance Taylor wrote: > On Fri, Aug 18, 2023 at 8:12 AM Tibor Halter <[email protected]> wrote: > > > > Hi Elias, thanks for chiming in! > > > > > The Go garbage collector is precise in that it only considers pointers > when determining memory that can be freed. > > > > Agreed, but it is not as precise on _what_ is a pointer. Specifically, > which matters? > > - the type used upon allocating the memory, or > > - the type used upon writing to it. > > > > Because *T or unsafe.Pointer is required upon writing to a memory > location for it to be marked as a pointer, I came to the conclusion that > the type upon writing is what matters. > > > > So then both types need to be pointers? > > > > Does that mean there is no way to define a struct-like memory layout > dynamically, that contains a mix of pointer and non-pointer types, in a way > that is supported by the GC? > > (This is what I'm trying to do.) > > The rule is pretty simple: a pointer must always have a pointer type. > That includes when it is in a variable and when it is stored in > memory. In your terms, what matters is the type used upon allocating > the memory. > > Your code is not following any of the patterns permitted for > unsafe.Pointer (any patterns that are not explicitly permitted are > forbidden). The code is effectively converting from *byte to *Num. > As it says at https://pkg.go.dev/unsafe#Pointer that kind of > conversion is only permitted if the types in question "share an > equivalent memory layout". byte and Num have different memory > layouts. > > You can define a struct-like memory layout dynamically by using > reflect.StructOf. > > Ian > > > > On Friday, August 18, 2023 at 3:49:03 PM UTC+2 [email protected] > wrote: > >> > >> On Friday, 18 August 2023 at 05:57:38 UTC-6 Tibor Halter wrote: > >> > >> Thanks Ian! > >> > >> I have managed to strip it down to its essence, see code below. > >> > >> Summary of what I'm doing > >> - reserve memory with make([]byte) > >> - get pointer to underlying array > >> - cast it to type Num > >> - write pointer #2 into it > >> - force GC() > >> - GC does not follow pointer #2, memory is freed > >> > >> > >> The Go garbage collector is precise in that it only considers pointers > when determining memory that can be freed. In your scenario and > demonstration program you explicitly store a pointer in a byte slice, > effectively making it invisible to the collector. > >> > >> > >> -- > >> > >> > >> package debug > >> > >> import ( > >> "testing" > >> "runtime" > >> "unsafe" > >> ) > >> > >> type Num struct { > >> numData *uint64 > >> } > >> > >> func Test(t *testing.T) { > >> n := uint64(123456789) > >> numMemSize := 8 > >> b := make([]byte, numMemSize, numMemSize) > >> sliceDataPtr := unsafe.Pointer(unsafe.SliceData(b)) > >> (*Num)(sliceDataPtr).numData = &n > >> > >> > >> The pointer to &n stored in b here is effectively hidden from the > collector. > >> > >> > >> > >> runtime.GC() > >> > >> > >> With no more visible references to (the supposedly heap-allocated) n, > it can be freed. > >> > >> > >> > >> act := (*Num)(sliceDataPtr).numData > >> if *act != 123456789 { > >> t.Fatalf("v[%X]", *act) > >> } > >> } > >> > >> > >> Elias > > > > -- > > 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]. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/5051da1c-36de-4699-906c-ff8f50754404n%40googlegroups.com > . > -- 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]. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1d6e5233-cef4-4466-8fee-9359ca69938dn%40googlegroups.com.
