post Image
golangではスタックとヒープを気にする必要が無い

調べようと思ったきっかけは、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のFAQ

golangのFAQにはスタックとヒープの扱いでは以下のように記載されています。
※全文はリンク先にて参照ください

[http://golang.jp/go_faq#stack_or_heap:title]

正確さを期するなら知る必要はありません。Goの各変数は参照されている限り存在し続けます。Goの実装によって選択された格納場所がどこかは、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 // ローカル変数がヒープに

コメントの箇所でコンパイラが関数の外で扱われると判断し、スタックではなくヒープに領域を確保しています。

newで確保したメモリを関数の外に出さない場合

では、コードを以下のようにするとどうでしょうか。

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

このコードの内容にはあまり意味はありませんが、newしたものを関数内で完結させています。
このコードの様子を再度出力してみます。

./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

golangの場合はnewで確保しても関数内で完結するものはヒープではなくスタックに割り当てられるようです。

このように、golangでは特にスタックかヒープかというのを特に意識しなくても問題はないようです。
長く、C/C++をやっていた人間からするとモヤモヤしますが。。。


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。