mishkamashka
mishkamashka

Reputation: 73

Go a reference assigned to a struct field escapes to heap

I'm trying to understand how this case is processed by escape analysis, it behaves differently when a field in structs is set on struct initialization and when it's set after struct initialization. Here's the code:

type X struct {
    p *int
}

func main() {
    var i1 int
    x1 := &X{
        p: &i1,
    }
    _ = x1

    var i2 int
    x2 := &X{}
    x2.p = &i2
}

Output of go build -gcflags="-m -m -m":

./main.go:7:6: can inline main with cost 31 as: func() { var i1 int; i1 = <nil>; x1 := &X{...}; _ = x1; var i2 int; i2 = <nil>; x2 := &X{}; x2.p = &i2 }
./main.go:8:6:[1] main stmt: var i1 int
./main.go:8:6:[1] main stmt: i1 = <nil>
./main.go:9:5:[1] main stmt: x1 := &X{...}
./main.go:9:2:[1] main stmt: var x1 *X
./main.go:12:4:[1] main stmt: _ = x1
./main.go:14:6:[1] main stmt: var i2 int
./main.go:14:6:[1] main stmt: i2 = <nil>
./main.go:15:5:[1] main stmt: x2 := &X{}
./main.go:15:2:[1] main stmt: var x2 *X
./main.go:16:7:[1] main stmt: x2.p = &i2
./main.go:14:6: i2 escapes to heap:
./main.go:14:6:   flow: {heap} = &i2:
./main.go:14:6:     from &i2 (address-of) at ./main.go:16:9
./main.go:14:6:     from x2.p = &i2 (assign) at ./main.go:16:7
./main.go:14:6: moved to heap: i2
./main.go:9:8: &X{...} does not escape
./main.go:15:8: &X{} does not escape

So why does i2 escape to heap? I guess it has something to do with the fact that compiler can't determine a lifetime of a variable at compile time. Though I don't understand why it is so.

Upvotes: 0

Views: 204

Answers (0)

Related Questions