在Go语言中,无需担心堆栈和堆的问题

我想查找的原因是在golang中,可以将局部变量的地址作为返回值而没有问题。

package main

import (
    "fmt"
)

type Animal struct {
    Name string
    Age  int
}

func main() {
    animal := allocAnimal()
    fmt.Printf("allocate animal structure %p", animal)
}

func allocAnimal() *Animal {
    return  &Animal{}
}

在C/C++中,当将局部变量的指针作为返回值时,由于需要将栈区的指针传递给函数外部,在编译时会显示警告信息(为什么不报错)。
在执行时最糟糕的情况是会发生段错误。
因此,需要使用malloc或new在堆区分配内存。
我很好奇为什么在Golang中允许这样做,所以进行了调查。

关于堆栈和堆的问题

以下是关于Golang中堆栈和堆的简要解释。

堆栈

    • 確保・解放が早い

 

    • 寿命が短い。関数内もしくは特定のスコープ内限定

 

    • サイズが小さい

 

    ローカル変数・引数などで使われる

    • 確保・解放が遅い

 

    • 寿命は自由

 

    • サイズが大きい

 

    newなどで確保される

Golang的常见问题解答

请在Golang的FAQ中查看有关堆栈和堆的处理的详细说明。请查看链接以获取完整内容。

在Go语言中,栈和堆的使用方式是如何的?

如果要确保正确性,就不需要知道。只要引用了Go的每个变量,它就会一直存在。在Go语言中,被选择的存储位置没有任何意义。

根据编译器的判断,如果变量的作用范围限定在函数内部,则被存储在栈中;如果变量在函数外也被引用,会被分配到堆中作为局部变量。

我实际上进行了调查。

当您向编译器传递标志时,您将了解内存分配的情况。

执行一下命令编译hello.go文件:go build -gcflags -m hello.go

我們來看一下原封不動的示範代碼。

$ go build -gcflags -m main.go
./main.go:17: can inline allocAnimal
./main.go:13: inlining call to allocAnimal
./main.go:14: animal escapes to heap
./main.go:13: &Animal literal escapes to heap
./main.go:14: main ... argument does not escape
./main.go:18: &Animal literal escapes to heap // ローカル変数がヒープに

在评论部分,编译器判断函数在外部处理,并在堆而非栈上分配空间。

如果你不将在函数外部分配的内存释放,-如果你没有释放在函数外部分配的内存,

那么,如果把代码改成下面这样会怎么样呢?

func allocAnimal() *Animal {
    animal := new(Animal)
    animal.Name = "Cat"
    animal.Age = 23
    return &Animal{}
}

这段代码的内容并没有太多意义,但是在函数内部使用了刚创建的对象来完成任务。
我将再次输出这段代码的状态。

./main.go:17: can inline allocAnimal
./main.go:13: inlining call to allocAnimal
./main.go:14: animal escapes to heap
./main.go:13: &Animal literal escapes to heap
./main.go:13: main new(Animal) does not escape // newしてもヒープに割り当てられない
./main.go:14: main ... argument does not escape
./main.go:22: &Animal literal escapes to heap
./main.go:18: allocAnimal new(Animal) does not escape

在Go语言中,对于在函数内部完成的对象,即使使用new方式进行分配,它们也会被分配到栈上,而不是堆上。

在Go语言中,似乎不需要特别意识到是使用堆还是栈的问题,这一点并不会引起太多困惑,尽管对于长期从事C/C++的人来说可能会感到疑惑。

广告
将在 10 秒后关闭
bannerAds