Need help to understand garbage collection in GoLa

2019-09-19 15:26发布

I'm a little bit confused with GoLang's garbage collector.

Consider this following code, where I implement reader interface for my type T.

type T struct {
   header Header
   data   []*MyDataType
}

func (t *T) Read(p []byte) (int, error) {
    t.Header = *(*Header) (t.readFileHeader(p))
    t.Data = *(*[]*MyDataType) (t.readFileData(p))
}

wherein the reader functions I will cast the data to MyDataType using the unsafe.Pointer which will point to slice created with the reflect module (this is more complicated, but for the sake of the example this should be enough)

func (t *T) readFileData(data []byte, idx int, ...) unsafe.Pointer {
    ...
    return unsafe.Pointer(&reflect.SliceHeader{Data : uintptr(unsafe.Pointer(&data[idx])), ...}) 
}

and If I am gonna read the data in different function

func (d *Dummy) foo() {
    data, _ := ioutil.ReadFile(filename)
    d.t.Read(data) <---will GC free data?
}

Now I'm confused if it is possible, that the GC will free loaded data from file after exiting the foo function. Or the data will be freed after the d.t is freed.

2条回答
Explosion°爆炸
2楼-- · 2019-09-19 16:01

According to the reflect docs, I've to keep a separate pointer to data *[]byte, to avoid garbage collection. So the solution is to add a referencePtr to

type T struct {
   header              Header
   data                   []*MyDataType
   referencePtr      *[]byte
}

which will point to my data inside the Read function

func (t *T) Read(p []byte) (int, error) {
    t.referencePtr = &p
    t.Header = *(*Header) (t.readFileHeader(p))
    t.Data = *(*[]*MyDataType) (t.readFileData(p))
}

or is this unnecessary?

查看更多
劳资没心,怎么记你
3楼-- · 2019-09-19 16:04

To understand what GC might do to your variables, first you need to know how and where Go allocates them. Here is a good reading about escape analysis, that is how Go compiler decides where allocate memory, between stack or heap.

Long story short, GC will free memory only if it is not referenced by your Go program.

In your example, the reference to loaded data by data, _ := ioutil.ReadFile(filename) is passed to t.Data = *(*[]*MyDataType) (t.readFileData(p)) ultimately. Therefore, they will be referenced as long as (t *T) struct is referenced as well. As far as I can see from your code, the loaded data will be garbage-collected along with (t *T).

查看更多
登录 后发表回答