为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
喵喔喔 2022-06-01 15:29:44
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使用了逃逸分析和垃圾回收。如果后一部分不存在,那么在极端情况下,根据规范,内存分配后立即取消分配是有效的实现。但这很荒谬,所以我认为规范应该使这一点无效。
查看完整描述

3 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

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

关于变量的部分说:

通过引用表达式中的变量来检索变量的值;它是分配给变量的最新值。如果一个变量还没有被赋值,它的值是它的类型的零值。

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


查看完整回答
反对 回复 2022-06-01
?
POPMUISE

TA贡献1765条经验 获得超5个赞

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

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

您找到的常见问题解答条目是规范的,可以依赖,与规范相同。


查看完整回答
反对 回复 2022-06-01
?
LEATH

TA贡献1936条经验 获得超7个赞

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

对于指针类型 *T 的操作数 x,指针间接 *x 表示 x 指向的类型 T 的变量。如果 x 为 nil,则尝试评估 *x 将导致运行时恐慌。

这基本上是说 Go 的实现一定会给你指向的值,除非指针nil在这种情况下会恐慌。规范没有说明实现是如何做到这一点的,但是您可以指望 Go 的任何实现以某种方式做到这一点。

这与您的第一句话所说的相符。


查看完整回答
反对 回复 2022-06-01
  • 3 回答
  • 0 关注
  • 164 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号