Go 内存分配 - 新对象、指针和转义分析

我读到Golang语言以一种聪明的方式管理内存。使用转义分析,go 在调用 new 时可能不会分配内存,反之亦然。golang可以用这样的符号分配内存吗 ?或者指针始终指向堆栈var bob * Person = & Person {2, 3}



慕尼黑8549860
浏览 104回答 3
3回答

慕妹3146593

指针可能会转义到堆中,也可能不转义,具体取决于您的使用案例。编译器非常智能。例如,给定:type Person struct {    b, c int}func foo(b, c int) int {    bob := &Person{b, c}    return bob.b}该函数将编译为:foo    TEXT    "".foo(SB)    MOVQ    "".b+8(SP), AX    MOVQ    AX, "".~r2+24(SP)    RET它全部位于此处的堆栈上,因为即使它是指针,它也不会逃脱此函数的作用域。bob但是,如果我们考虑轻微的(尽管是人为的)修改:var globalBob *Personfunc foo(b, c int) int {    bob := &Person{b, c}    globalBob = bob    return bob.b}然后转义,并将编译为:bobfoo    TEXT    "".foo(SB), ABIInternal, $24-24    MOVQ    (TLS), CX    CMPQ    SP, 16(CX)    PCDATA  $0, $-2    JLS     foo_pc115    PCDATA  $0, $-1    SUBQ    $24, SP    MOVQ    BP, 16(SP)    LEAQ    16(SP), BP    LEAQ    type."".Person(SB), AX    MOVQ    AX, (SP)    PCDATA  $1, $0    CALL    runtime.newobject(SB)    MOVQ    8(SP), AX    MOVQ    "".b+32(SP), CX    MOVQ    CX, (AX)    MOVQ    "".c+40(SP), CX    MOVQ    CX, 8(AX)    PCDATA  $0, $-2    CMPL    runtime.writeBarrier(SB), $0    JNE     foo_pc101    MOVQ    AX, "".globalBob(SB) foo_pc83:    PCDATA  $0, $-1    MOVQ    (AX), AX    MOVQ    AX, "".~r2+48(SP)    MOVQ    16(SP), BP    ADDQ    $24, SP    RET如您所见,它调用 .newobject这些反汇编列表由 https://godbolt.org/ 生成,在 amd64 上为 go 1.16 生成

江户川乱折腾

是将内存分配给堆栈上还是“转义”到堆中,完全取决于您如何使用内存,而不是如何声明变量。如果返回指向堆栈分配变量的指针(例如 C),则当您尝试使用它时,指针的值将无效。这在 Go 中是不可能的,因为您无法显式告诉 Go 将变量放置在何处。它在选择正确的位置方面做得很好,如果它看到对内存 blob 的引用可能位于堆栈帧之外,它将确保在堆上进行分配。golang可以用这样的符号分配内存吗?var bob * Person = & Person {2, 3}或者指针始终指向堆栈不能说这行代码“总是”指向堆栈,但它有时可能会,所以是的,它可能会分配内存(在堆上)。同样,这不是关于那行代码,而是关于它之后会发生什么。如果返回值 (对象的地址),则无法在堆栈上分配它,因为返回的地址将指向回收的内存。bobPerson

守着一只汪

简而言之,如果编译器可以证明该值可以在堆栈上安全地创建,那么它将(可能)在堆栈上创建。否则,它将在堆上分配。编译器必须执行这些证明的工具非常好,但它并不总是正确。然而,大多数时候,担心它的成本与收益并没有真正的好处。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go