やっつけな日常(25) Goに入ればGoに従え、そんなこと出来るの?ヒープ・エスケープ

Joseph Halfmoon

前回はRust言語のヒープ管理が「クセが強い」みたいな事を書いてしまいました。「クセが強い」ことでは、Go言語のヒープ管理も負けてない、と思います(個人の感想です。)「ヒープ・エスケープ」という技?を最初みたときには、これは何?と結構驚きました。伝統的なC言語ではやっちゃいけない(やったらひどいことになる)ことがOK。

※今回はWSL1上のUbuntu20.04LTSにインストールした以下のバージョンのGoで確認してます。goVersion

ヒープ・エスケープ(heap escape)

GoもRustも、ヒープの管理は、Cのようなプログラマ管理のalloc/freeではなくモダーンな感じに自動です。しかしその開放の仕方は異なっていて、今回やってみるGoはギャベージ・コレクタ(GC)を使っています。

ヒープをアサインする方法も独特です。Go言語の場合、ヒープに置くべきだとコンパイラが判断したメモリオブジェクト(変数含む)は勝手にヒープに置かれます。もちろんスタックに置いても大丈夫なものはスタックに置かれます。C言語ではstaticでないローカル変数が必ずスタックの上にとられるのとは大違いです。Goのこの仕組みをヒープ・エスケープと言うそうです。スタックから逃げるってことなのかい?知らんけど。

以下は単純変数を殊更にヒープ・エスケープするように書いてみた例です。tst1関数はヒープ・エスケープされ、tst2関数はされません。

memESC000

目論見どおり動作することを確認するため実行してみたところが以下に。問題なく実行されているみたいです。

memESC000result

ううむ、Cでtst1みたいなこと「関数内部で宣言したローカル変数へのポインタを該当の関数を抜けてから使う」をすると、たまたま動いているように見える(まだスタックが再利用されていない場合)こともあるかと思いますが、まったく関係ない変数にアクセスしてしまったり、システムによってはメモリ保護に引っかかってクラッシュするようなことも考えられます。ヤバいやつ。

Go言語のやり方は確かに便利で、慣れるとハマりそうな気もするのです(Goでコード書くときには毎度お世話になってます。)でもGoの外でついやってしまいそうで心配、恐ろしいデス。Goに入ればGoに従えと。しつこいな。

やっつけな日常(24) Rustに入ればRustに従え、メモリの管理、独特、でも安全かも。

やっつけな日常(26) Jsに入ればJsに従え、JavaScriptの「巻き上げ」、御無体な