代码之家  ›  专栏  ›  技术社区  ›  techStud

为什么Go在变量超出作用域后立即取消引用悬挂指针时不会抛出错误?

  •  0
  • techStud  · 技术社区  · 1 月前

    我正在学习Gos的内存管理和垃圾回收,当指针指向的变量超出作用域后,我试图解引用指针时遇到了一些意外行为。

    在Go中,我理解垃圾回收(GC)是自动的,指针有时会引用不再有效的内存。我原以为取消引用指向作用域外变量的指针会抛出错误,但看起来Go在这样做时确实会抛出错误

    以下是一个演示该问题的最小示例:

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func main() {
        var p *int
        {
            x := 42
            p = &x  // p points to x
            fmt.Println(*p) // Prints 42
        }
    
        // Force garbage collection (for testing)
        runtime.GC()
    
        // Dereferencing p here should cause an error (since x is out of scope)
        fmt.Println(*p) // This does NOT throw any error
    }
    

    我所期待的:

    • 我原本预计,在x超出作用域的内部块之后,指针p将是一个“悬空指针”,并且在解引用时会立即导致运行时错误。
    • 我预期的错误类似于:运行时:无效的内存地址或零指针解引用。

    实际情况:

    • 即使在强制垃圾回收后,程序在取消引用*p时也不会死机或抛出错误。即使x超出范围,打印的值仍然是x的地址。
    1 回复  |  直到 1 月前
        1
  •  3
  •   Burak Serdar    1 月前

    GC不关心范围。它检查是否有指向内存对象的活动指针。就你而言,至少有一个。

    变量 x 可能超出范围,但是 p 不是,而是指向 x ,并且有一个goroutine使用 p ,所以 x 不会被垃圾回收。函数返回后,它将准备好进行收集,因为 p 也将超出范围。