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


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

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

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

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

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

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

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

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

func foo() *int {
x := 42
return &x
}
func main() {
px := foo()
fmt.Println(*px)
}

更准确地说,我预计"Go在new或其他情况下分配内存"one_answers"Go至少保留所分配的内存"这两部分应该写在规范中。我不关心它的实现细节,尽管https://github.com/golang/go使用转义分析和垃圾收集。

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

编辑结束:我不认为这个问题是基于意见的。这个问题是一个简单的是/否问题,询问规范中的描述。存在/不存在的原因可以通过引用来回答。如果没有,请显示/评论哪些观点是基于意见的。我会改进的

规范使用术语变量表示存储位置。规范没有区分堆或堆栈上的存储位置。规范中没有术语heapstack

关于变量的部分说:

通过引用表达式中的变量来检索变量的值;它是分配给变量的最新值。如果变量尚未赋值,则其值为其类型的零值。

如果可以引用变量,则可以检索该变量的值。当存在对变量的现有引用时,编译器和运行时必须保留变量的值。

但是有保存部分的描述吗?我们能确认"Go中的每个变量都存在,只要有引用"这一事实吗?如果没有,有什么原因吗?

不在语言规范中,否;这是运行时的质量,而不是语言。我们可以通过观察Go程序的实际工作来确认这样一个事实,即只要有引用,内存就不会被收集。如果这个假设不成立,那么大多数标准库以及几乎所有Go开发人员编写的代码都将无效。Go编译器的转义分析和垃圾收集器肯定可以工作。

您找到的FAQ条目是规范的,可以信赖,与规范相同

您可以想象会导致问题的是主函数中的*px。如果px所指向的东西已经不存在了。但是,根据本节:https://golang.org/ref/spec#Address_operators

对于指针类型为*T的操作数x,指针间接性*x表示x所指向的类型为T的变量。如果x为零,则尝试计算*x将导致运行时死机。

这基本上意味着Go的实现一定会给你所指向的值,除非指针是nil,在这种情况下它会死机。规范没有说明实现是如何做到这一点的,但您可以指望Go的任何实现都能做到这一步。

这与你的第一句话相吻合。

相关内容

最新更新