メモリ管理のアプローチ
従来、言語は大まかに 2 つのカテゴリに分けられてきました。
- 手動メモリ管理による完全な制御: C, C++, Pascal, …
- プログラマが、いつヒープメモリを割り当てたり解放したりするかを決めます。
- ポインタが依然として有効なメモリを指しているかどうかを、プログラマが判断しなければなりません。
- 研究が示すように、プログラマはミスを犯します。
- 実行時の自動メモリ管理による完全な安全性: Java, Python, Go, Haskell, …
- ランタイムシステムが、メモリが参照できなくなるまで解放されないことを 保証します。
- 通常は、参照カウントまたはガベージコレクションで実装されます。
Rust は新たな組み合わせを提供します。
正しいメモリ管理をコンパイル時に強制することによる、完全な制御 と 安全性。
これは、明示的な所有権の概念によって実現されています。
このスライドは、他の言語から来た受講者が Rust を文脈の中で位置づけて 理解するのに役立つことを意図しています。
-
C では、
mallocとfreeを使ってヒープを手動で管理しなければなりません。よくあるエラーには、freeの呼び出し忘れ、同じポインタに対して複数回呼び出すこと、あるいはそのポインタが指している メモリがすでに解放された後にそのポインタをデリファレンスすることが含まれます。 -
C++ には、スマートポインタ(
unique_ptr,shared_ptr)のようなツールがあり、 デストラクタ呼び出しに関する言語の保証を活用して、関数から戻るときにメモリが 解放されることを確実にします。それでもなお、これらのツールを誤用して、 C と同様のバグを作り込んでしまうのはかなり簡単です。 -
Java、Go、Python は、もはや到達不能になったメモリをガベージコレクタが特定して 廃棄することに依存しています。これにより、あらゆるポインタをデリファレンスできることが 保証され、use-after-free やその他の種類のバグが排除されます。しかし、GC には実行時コストがあり、適切にチューニングするのは困難です。
Rust の所有権と借用のモデルは、多くの場合、必要な箇所に正確に alloc と free の 操作を配置しながら、C の性能を実現できます – ゼロコストです。また、C++ の スマートポインタに似たツールも提供します。必要に応じて、参照カウントのような 他の選択肢も利用でき、実行時ガベージコレクションをサポートするクレートさえ 存在します(この授業では扱いません)。