D
D
di2019-12-18 11:21:04
go
di, 2019-12-18 11:21:04

Why is the pointer changing?

Why does the pointer change in this example.
https://play.golang.org/p/P76IDHg6ZA3

package main

func main() {
    var val int
    println(&val)
    f(10000)
    println(&val)
}

func f(i int) {
    if i--; i == 0 {
      return
    }
    f(i)
}

I assumed that it was the work of the garbage collector. But even with garbage collection disabled, the pointer changes.
And if you use fmt.Println, then the pointer does not change
https://play.golang.org/p/ugjBjFNVO4h
package main

import "fmt"

func main() {
    var val int
    println(&val)
    f(10000)
    println(&val)
    fmt.Println(&val)
}

func f(i int) {
    if i--; i == 0 {
      return
    }
    f(i)
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vladislav, 2019-12-18
@Delgus

By default, the val variable is located on the stack, but when using fmt.Println(), the variable "runs away" into the heap.
Since the parameters to the function are passed through the stack, this shifts the pointer to the variable.
This is clearly visible if you open the debugger and look at the change in registers.
You can run escape analysis with the command:
go run -gcflags "-m" test.go

$ go run -gcflags "-m" test.go 
# command-line-arguments
./test.go:13:13: inlining call to fmt.Println
./test.go:9:6: moved to heap: val
./test.go:13:14: &val escapes to heap
./test.go:13:13: main []interface {} literal does not escape
./test.go:13:13: io.Writer(os.Stdout) escapes to heap
<autogenerated>:1: (*File).close .this does not escape
0xc00001a0a8
0xc00001a0a8
0xc00001a0a8

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question