Go内存分配——新对象、指针和逃逸分析

Nak*_*em1 2 memory go

我读到 Golang 语言以一种智能的方式管理内存。使用逃逸分析,go在调用new时可能不会分配内存,反之亦然。golang可以用这样的表示法分配内存吗var bob * Person = & Person {2, 3}?或者指针总是指向堆栈

Eli*_*sky 6

指针可能会逃逸到堆,也可能不会,具体取决于您的用例。编译器非常聪明。例如给出:

type Person struct {
    b, c int
}


func foo(b, c int) int {
    bob := &Person{b, c}
    return bob.b
}
Run Code Online (Sandbox Code Playgroud)

该函数foo将被编译为:

    TEXT    "".foo(SB)
    MOVQ    "".b+8(SP), AX
    MOVQ    AX, "".~r2+24(SP)
    RET
Run Code Online (Sandbox Code Playgroud)

它都在这里的堆栈上,因为即使bob是一个指针,它也不会逃脱这个函数的作用域。

然而,如果我们考虑一个轻微的(尽管是人为的)修改:

var globalBob *Person

func foo(b, c int) int {
    bob := &Person{b, c}
    globalBob = bob
    return bob.b
}
Run Code Online (Sandbox Code Playgroud)

然后bob转义,并foo会被编译为:

    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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这会调用newobject.


这些反汇编列表由https://godbolt.org/生成,适用于 amd64 上的 go 1.16