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/f299fa55-9046-45bd-ba5c-0904bd6c3e0an%40googlegroups.com.