【问题标题】:Need help to understand garbage collection in GoLang需要帮助了解 GoLang 中的垃圾收集
【发布时间】:2019-07-24 22:55:12
【问题描述】:

我对 GoLang 的垃圾收集器有点困惑。

考虑以下代码,我在其中为我的类型 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))
}

在阅读器函数中,我将使用 unsafe.Pointer 将数据转换为 MyDataType,这将指向使用反射模块创建的切片(这更复杂,但对于示例而言,这应该足够了)

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

如果我要在不同的函数中读取数据

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

现在我很困惑,如果有可能,GC 会在退出 foo 函数后从文件中释放加载的数据。或者d.t被释放后数据会被释放。

【问题讨论】:

  • 如果你有一个指向某个东西的指针,GC 不会释放它。您遇到问题了吗?
  • 其次,GC 非常可靠,所以除非你真的遇到问题,否则这似乎是在调试假设,因此没有必要。

标签: go garbage-collection unsafe-pointers


【解决方案1】:

要了解 GC 可能对您的变量做什么,首先您需要了解 Go 分配它们的方式和位置。这是关于 escape analysis 的好读物,这就是 Go 编译器如何决定在堆栈或堆之间分配内存的方式。

长话短说,只有在你的 Go 程序没有引用内存时,GC 才会释放内存。

在您的示例中,data, _ := ioutil.ReadFile(filename) 对加载数据的引用最终传递给t.Data = *(*[]*MyDataType) (t.readFileData(p))。因此,只要(t *T) struct 也被引用,它们就会被引用。据我从您的代码中可以看出,加载的数据将与(t *T) 一起被垃圾收集。

【讨论】:

    【解决方案2】:

    根据reflect docs,我必须保留一个指向data *[]byte 的单独指针,以避免垃圾收集。所以解决方案是在

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

    这将指向我在读取函数中的数据

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

    或者这是不必要的?

    【讨论】:

    • 编辑您的问题以进行后续跟进。
    猜你喜欢
    • 2011-10-12
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 2012-04-14
    • 1970-01-01
    • 2021-03-25
    相关资源
    最近更新 更多