Delgus
@Delgus

Почему меняется указатель?

Почему в данном примере меняется указатель.
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)
}

Я предполагал что дело а работе garbage collector. Но даже с отключенной сборкой мусора указатель меняется.

А если использовать fmt.Println, то указатель не меняется
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)
}
  • Вопрос задан
  • 169 просмотров
Решения вопроса 2
@ghostiam
На Go писатель, серверов пинатель.
По умолчанию, переменная val располагается на стеке, но при использовании fmt.Println() переменная "убегает" в heap.
Так как параметры в функцию передаются через стек, из за этого сдвигается указатель на переменную.
Это хорошо видно, если открыть дебагер и посмотреть изменение регистров.

Запустить escape analysis можно с помощью команды:
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
Ответ написан
Комментировать
@rustler2000
погромист сикраш
У горутин маленький стэк в начале, и это не стэк треда.
Рекурсивный func f вызывает рост стэка (в го нет TCO и похоже не будет), и переаллокацию бОльшего стэка из другого size class (смотри tcmalloc) с последующим копированием.
Смещение переменной в стэке осталось таким же, но адрес изменился.

Ну а при fmt.Printf переменная в хипе и с постоянным адресом. Вроде на github было даже этому объяснение, из-за чего escape analysis так себя ведёт.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы