es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo saber si una variable asignada en golang está en el heap o en el stack?

Leí el FAQ de Golang: https://go.dev/doc/faq#stackoheap, quiero saber cuándo Golang asigna una variable en la pila o en el montón. Así que escribí un código como el siguiente:

“`
paquete principal

import (
“fmt”
)

type Object struct {
Campo int
}

func main() {
A := Object{1}
B := Object{2}
fmt.Println(A, B)
//fmt.Printf(“A:%p;B:%p\n”,&A,&B)
//m := testStackOrHeap()
//C:=m[A]
//D:=m[B]
//fmt.Printf(“C:%p;D:%p\n”,&C,&D)
}

//go:noinline
func testStackOrHeap() map[Object]Object {
uno := 1
dos := 2
A := Object{uno}
B := Object{dos}
C := Object{uno}
D := Object{dos}
fmt.Println(C,D)
fmt.Printf(“A:%p;B:%p\n”,&A,&B)
m := map[Object]Object{A: A, B: B}
return m
}


luego vea cómo el compilador asigna la memoria. El comando es go tool compile " -m " main.go
la salida es la siguiente:

main.go:15:13: llamada de en línea a fmt.Println
main.go:30:13: llamada de en línea a fmt.Println
main.go:31:12: llamada de en línea a fmt.Printf
main.go:15:13: A escapa al montón
main.go:15:13: B escapa al montón
main.go:15:13: literal []interface {} no escapa
main.go:26:2: movido al montón: A
main.go:27:2: movido al montón: B
main.go:30:13: C escapa al montón
main.go:30:13: D escapa al montón
main.go:30:13: literal []interface {} no escapa
main.go:31:12: literal []interface {} no escapa
main.go:32:24: literal map[Object]Object escapa al montón
: 1: .this no escapa

mi pregunta es:
¿Por qué Golang no asigna las variables A y B en testStackOrHeap() a la pila, si no pueden escapar al marco de la pila, si se asigna al montón, el recolector de basura necesitará recopilarlo, pero si se asigna en la pila, se liberará cuando la función regrese?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Según la salida del compilador, las variables A y B dentro de la función testStackOrHeap() se mueven al heap porque escapan al heap. Esto significa que hay una referencia a estas variables que se extiende más allá de la vida útil de la llamada a la función.

    En este caso, los valores de A y B se utilizan como claves en un mapa, que es devuelto por la función. Dado que el mapa se almacena en el heap, las claves A y B también deben asignarse en el heap para que sigan siendo válidas incluso después de que la función regrese.

    Aunque A y B no escapan al marco de la pila, asignarlos en la pila puede no ser seguro en todos los casos. Si son referenciados por otros objetos que aún están vivos después de que la función regrese, acceder a su memoria en la pila podría resultar en un comportamiento indefinido. Por lo tanto, el compilador de Go se inclina por la precaución y los asigna en el heap para garantizar su validez.

Comments are closed.