Rustについて基本からしっかり学んでいく本連載。第17回は、スマートポインタを中心にしたRustにおけるメモリ管理について。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
ポインタという言語仕様は、多くのプログラミング言語に存在します。特にC言語で重要なポジションを占めている印象が強いですが、値の実体を持たずに「場所」のみの情報で値へのアクセスが可能なため、融通性と効率性に優れています。反面、使いこなしが難しいとされ、言語習得の上でのハードルであったり、バグ発生の大きな要因とされたりすることも多い存在です。ただし、使いこなせれば強力な武器となるのは間違いありません。今回は、このポインタがテーマです。
Rustでもポインタが使えます。それが、「参照」と「スマートポインタ」です。参照は、連載第6回で紹介しました。値を「&」演算子によって借用すると、それは参照となり、所有権を持たずに値へアクセスできる、というものです。これはまさにポインタの働きそのものです。参照は値を指し示すだけなので、その利用においてオーバーヘッドのようなものはありません。その代わり、値を指し示す以外の特別な機能もありません。シンプルなため、関数の引数や戻り値など、コードのさまざまな局面で利用されます。
スマートポインタとは、「スマート」(賢い)と名前に付いているように、メモリの管理を自動化したポインタです。もともとC++言語で導入された概念ですが、Rustでも導入されて、メモリ安全において重要な役割を担っています。
本連載ではスマートポインタをすでに使用してきました。文字列(String)やベクター(Vec<T>)などです。String型では保有する文字列の実体はヒープに置き、String型の構造体自身はスタックに置かれて、その場所を保持するだけということを、連載第5回において紹介しました。この際、文字列のためのメモリは自動的に確保され、不要になると自動的に解放されるということにも触れました。このようにスマートポインタは、プログラマーが意識することなく、値のためのメモリを安全に確保、解放できるようになっています。これは、ベクターなどでも同様です。
スマートポインタは、その目的に応じてさまざまな実装があります。既出であるString型、Vec<T>型を含めて、以下に代表的なものを挙げます。
次節では、ベーシックなスマートポインタの実装であるボックス(Box<T>型)を紹介し、これを通じてスマートポインタの動作を掘り下げていきます(Rc<T>/Arc<T>、Cell<T>/RefCell<T>については、最後に概要のみを示します)。なお、このBox<T>型は、連載第15回でエラーを返す汎用的な型として少しだけ登場しました。
値の格納場所には、大きくスタックとヒープがあります。それぞれに特性があるので、使い分けることになっています。スタックは比較的小さなメモリ領域で、スカラー型や参照、小さな構造体の格納に適しています。スタックに置かれた値は、スコープから外れると自動的に解放されるので管理も容易です。ヒープは大きなメモリ領域で、配列や文字列などのサイズの大きな値の格納に適しています。ただし、ヒープに確保した値は明示的な解放が必要です。スマートポインタは、ヒープからの確保と解放を自動化して、サイズの大きな値の扱いを容易にしているのです。
Copyright © ITmedia, Inc. All Rights Reserved.