GC是否会将整个对象保留在内存中,而内部指针仍保留到一个字段?这会导致内存泄漏吗?

时间:2019-03-06 08:29:44

标签: go memory-leaks

go的GC是否将整个对象保留在内存中,而保留指向字段的内部指针?

这样会导致内存泄漏吗?还是go的GC“足够智能”以注意到不再需要其余对象并将其从内存中清除?

package main

import (
    "fmt"
)

const aLot = 500000000

func getInteriorPointer() *int {
    type bigStruct struct {
        someBigThing [aLot]int
        smallThing   int
    }
    b := bigStruct{smallThing: 3}
    return &b.smallThing
}

func main() {
    p := getInteriorPointer()
    // keep using p in the rest of the app, 
    // never using someBigThing from the struct
    fmt.Println(*p)
}

2 个答案:

答案 0 :(得分:3)

是的。内存将一直保留,直到不再引用分配的任何部分为止。

通常的例子以切片技巧给出

  

SliceTricks

     

删除而不保留​​顺序

a[i] = a[len(a)-1] 
a = a[:len(a)-1]
     

注意如果元素的类型是指针或带指针的结构   上面的实现中需要垃圾回收的字段   “剪切”和“删除”操作有潜在的内存泄漏问题:某些元素   值仍被切片a引用,因此不能   收集。

答案 1 :(得分:-1)

看着分析器,似乎确实是内存泄漏(go1.11.5 darwin / amd64)


让我们看一下探查器。

我找到了an online example for debugging memory。通过适应我的示例,我做到了:

package main

import (
    "fmt"
    "os"
    "runtime"
    "runtime/debug"
    "runtime/pprof"
)

const aLot = 5000000

func getInteriorPointer() *int {
    type bigStruct struct {
        someBigThing [aLot]int
        smallThing   int
    }
    b := bigStruct{smallThing: 3}
    return &b.smallThing
}

func main() {
    p := getInteriorPointer()
    runtime.GC()
    debug.FreeOSMemory()
    fmem, _ := os.Create("prof.prof")
    pprof.WriteHeapProfile(fmem)

    // keep using p in the rest of the app,
    // never using someBigThing from the struct
    fmt.Println(*p)
}

现在我运行go tool pprof prof.proflist main

ROUTINE ======================== main.getInteriorPointer in /Users/karel/exp/exp.go
   38.15MB    38.15MB (flat, cum)   100% of Total
         .          .     13:func getInteriorPointer() *int {
         .          .     14:   type bigStruct struct {
         .          .     15:           someBigThing [aLot]int
         .          .     16:           smallThing   int
         .          .     17:   }
   38.15MB    38.15MB     18:   b := bigStruct{smallThing: 3}
         .          .     19:   return &b.smallThing
         .          .     20:}
         .          .     21:
         .          .     22:func main() {
         .          .     23:   p := getInteriorPointer()
ROUTINE ======================== main.main in /Users/karel/exp/exp.go
         0    38.15MB (flat, cum)   100% of Total
         .          .     18:   b := bigStruct{smallThing: 3}
         .          .     19:   return &b.smallThing
         .          .     20:}
         .          .     21:
         .          .     22:func main() {
         .    38.15MB     23:   p := getInteriorPointer()
         .          .     24:   runtime.GC()
         .          .     25:   debug.FreeOSMemory()
         .          .     26:   fmem, _ := os.Create("prof.prof")
         .          .     27:   pprof.WriteHeapProfile(fmem)
         .          .     28:

似乎垃圾回收器确实不会从内存中删除不必要的对象。 如果我正确理解了格式。 (我可能不会,因为几乎没有文档。)