golangで関数内の自動変数のポインタを返却してしまった場合


これはSIGSEGVを出しませんが、なぜですか？

[code]

    package main
    
    import "fmt"
    
    func get_pointer() *int{
        var x int = 1
        fmt.Println(&x)
        return &x
    }
    
    func main() {
        xp := get_pointer()
        *xp = 100
        fmt.Println(xp)
        fmt.Println(*xp)
    }
    
[/code]

[code]

    0xc00002c008
    0xc00002c008
    100
    
[/code]




変数 `x` がスタックではなくヒープ領域に確保されたためです。

[code]

    $ go run -gcflags '-m' main.go
    # command-line-arguments
    ./main.go:7:13: inlining call to fmt.Println
    ./main.go:14:13: inlining call to fmt.Println
    ./main.go:15:13: inlining call to fmt.Println
    => ./main.go:6:6: moved to heap: x <=
    ./main.go:7:13: []interface {} literal does not escape
    ./main.go:14:13: []interface {} literal does not escape
    ./main.go:15:14: *xp escapes to heap
    ./main.go:15:13: []interface {} literal does not escape
    <autogenerated>:1: .this does not escape
    0xc000014178
    0xc000014178
    100
    
[/code]

これは golang の escape analysis と呼ばれる機能です。興味を持たれましたら [Allocation efficiency in
high-performance Go services](https://segment.com/blog/allocation-efficiency-
in-high-performance-go-services/) の "Some Pointers" を参照してみて下さい。




変数 `x` がスタックではなくヒープ領域に確保されたためです。

[code]

    $ go run -gcflags '-m' main.go
    # command-line-arguments
    ./main.go:7:13: inlining call to fmt.Println
    ./main.go:14:13: inlining call to fmt.Println
    ./main.go:15:13: inlining call to fmt.Println
    => ./main.go:6:6: moved to heap: x <=
    ./main.go:7:13: []interface {} literal does not escape
    ./main.go:14:13: []interface {} literal does not escape
    ./main.go:15:14: *xp escapes to heap
    ./main.go:15:13: []interface {} literal does not escape
    <autogenerated>:1: .this does not escape
    0xc000014178
    0xc000014178
    100
    
[/code]

これは golang の escape analysis と呼ばれる機能です。興味を持たれましたら [Allocation efficiency in
high-performance Go services](https://segment.com/blog/allocation-efficiency-
in-high-performance-go-services/) の "Some Pointers" を参照してみて下さい。

