メモリ管理について
Rustの最も特徴的な部分といえば、そのメモリ管理の手法にあります。高パフォーマンスな実装をするためには、メモリの理解が必要です。
メモリには、以下の2つがあります。
- スタックメモリ
- ヒープメモリ
スタック
- スタックは、各関数で作成される変数を格納するメモリの領域です。
- スタックフレームは、各関数のメモリです。
基本的に、変数は作成されたスタックフレーム内でのみアクセスできます。いわゆるスコープです。
関数が終了するとスタックフレームは開放されます。つまりスタックメモリの開放は関数の終了時に自動的に行われます。
関数や変数が作成されるとどんどんスタックに積み重なって行きます。無限ループなどでスタックがメモリ容量の限界を越えるといわゆる「スタックオーバーフロー」となります。
ヒープ
ヒープはプロセスメモリの領域であり、自動的には管理されません。従ってメモリの開放を手動で行う必要があります。
これを怠ると、いわゆる「メモリリーク」となります。
- ヒープはスタックと異なり、容量の際限がありません
- 従って大容量のデータを扱うことができます
- どの関数からでも自由にアクセスすることができる領域です
ヒープ領域へのアクセス
ヒープに保存された変数には、アドレス(住所/番地)のような物が紐づきます。
このアドレスを参照することで、保存された変数にアクセスすることができます。
ヒープメモリは手動で開放する必要があるのでした。
仮に、開放しないままアドレスを参照している関数が終了した場合、ヒープ内の変数にアクセスする方法がなくなってしまいます。アドレスを知っている関数が存在しないからです。
これがメモリリークであり、つまり二度とアクセスできない変数がメモリに溜まってしまいます。
スマートポインタ
このように、ガベージコレクションのない低級言語においては手動でメモリの開放を行います。
これは面倒であると同時にバグの温床になります。そこでRustやC++などにはスマートポインタと呼ばれる機能があります。
スマートポインタはメモリの開放を保証するようなものです。
- ヒープのアドレスをスマートポインタに紐付けて管理します。
- スタックフレームはアドレスを直接参照せず、スマートポインタを保持します。
- スタックフレームの開放と同時に、スマートポインタに紐づけられたヒープメモリも同時に開放するように約束します。
これによって、メモリリークを防ぐことができます。