猿问

Go 的分配内存的生命周期模型是否有规范?

Go 使用逃逸分析和垃圾收集来管理堆栈和堆上的内存分配。Go 的常见问题解答还说:

我如何知道变量是分配在堆上还是栈上?

从正确性的角度来看,您不需要知道。只要有对它的引用,Go 中的每个变量就存在。实现选择的存储位置与语言的语义无关。

所以 Go 为变量分配内存,并至少保留它直到需要它。

我的问题是:这个(抽象)行为是用Go 编程语言规范编写的吗?我发现分配部分是写的,例如,在分配部分

内置函数new采用 type T,在运行时为该类型的变量分配存储空间,并返回*T指向该类型的值。

但是有没有关于预订部分的描述?我们能否确认“Go 中的每个变量只要有引用就存在”这一事实吗?如果没有,有什么原因吗?

例如,如果 Go 编译器没有错误,我想确认以下程序不得抛出 SIGSEGV 或类似异常。

func foo() *int {

    x := 42

    return &x

}

func main() {

    px := foo()

    fmt.Println(*px)

}

更准确地说,我希望“Go 在new什么时候分配内存”和“Go 至少在需要时保留分配的内存”这两部分应该写在规范中。我不关心它的实现细节,尽管https://github.com/golang/go使用了逃逸分析和垃圾回收。


如果后一部分不存在,那么在极端情况下,根据规范,内存分配后立即取消分配是有效的实现。但这很荒谬,所以我认为规范应该使这一点无效。


喵喔喔
浏览 166回答 3
3回答

繁星coding

该规范使用术语变量来表示存储位置。该规范不区分堆或堆栈上的存储位置。规范中没有术语堆和堆栈。关于变量的部分说:通过引用表达式中的变量来检索变量的值;它是分配给变量的最新值。如果一个变量还没有被赋值,它的值是它的类型的零值。如果可以引用变量,则可以检索变量的值。当存在对变量的现有引用时,编译器和运行时必须保留变量的值。

POPMUISE

但是有保存部分的说明吗?我们能否确认“Go 中的每个变量只要有引用就存在”这一事实吗?如果没有,有什么原因吗?不在语言规范中,不;这是运行时的质量,而不是语言。我们可以通过简单地观察 Go 程序实际工作来确认只要有对它的引用就不会收集内存的事实。如果该假设不成立,那么大多数标准库以及几乎所有 Go 开发人员编写的代码都将无效。Go 编译器的逃逸分析和垃圾收集器绝对有效。您找到的常见问题解答条目是规范的,可以依赖,与规范相同。

LEATH

您可以想象会导致问题的事情是*px在 main 函数中。如果指向的东西px不再存在。但是,根据本节:https ://golang.org/ref/spec#Address_operators对于指针类型 *T 的操作数 x,指针间接 *x 表示 x 指向的类型 T 的变量。如果 x 为 nil,则尝试评估 *x 将导致运行时恐慌。这基本上是说 Go 的实现一定会给你指向的值,除非指针nil在这种情况下会恐慌。规范没有说明实现是如何做到这一点的,但是您可以指望 Go 的任何实现以某种方式做到这一点。这与您的第一句话所说的相符。
随时随地看视频慕课网APP

相关分类

Go
我要回答