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.

Reply via email to