「Rustは安全でも難しい」といわれる理由――メモリ安全を実現する「所有権」の仕組み基本からしっかり学ぶRust入門(5)

Rustについて基本からしっかり学んでいく本連載。今回はRustにおける核心的な機能でRustによるメモリ安全なプログラミングを実現する機能の代表となる所有権を解説します。

» 2021年11月25日 05時00分 公開

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「基礎からしっかり学ぶRust入門」のインデックス

連載:基礎からしっかり学ぶRust入門

 本連載のサンプルコードをGitHubで公開しています。こちらからダウンロードしてみてください。具体的な利用方法は連載第1回を参考にしてください。


所有権とは?

 本連載の第1回〜第4回では、Rustの基本的な文法を主にC/C++と対比させて紹介してきました。そこで取り上げなかったものに「ポインタ」があります。ポインタはC/C++では非常に便利である反面、メモリ安全性を妨げるとされています。Rustにもポインタがありますが、C/C++とは違い安全に利用できます。安全にポインタを利用できるようにしているのが「所有権」であり、「借用」です。まずは、所有権のルールを見ていきましょう。

所有権の基本的なルール

 所有権とは、文字通り変数が値を所有できる権利のことです。そして、その権利を持つ変数を「所有者」といいます。Rustではある値の所有者は常に1つとなるように決められています。さらに、変数がスコープから抜けるときには、一緒に値も破棄されます。これらが所有権の基本的なルールになります。

 もしこのルールから外れたコードを書いた場合は、それはコンパイラに捕捉されてエラーとなるためプログラムを実行できません。そのため所有権のルールは非常に重要と言えますが、けして難しく考える必要はありません。スカラー型などの変数と文字列型(String型)の変数を例にとり、その振る舞いを見ながら理解していきましょう。

【補足】Rustにおけるスコープ

 Rustにも、プログラミングで一般的な概念としてのスコープ(scope)があります。スコープとは「範囲」という意味ですが、Rustにおいては変数の有効な範囲ということになります。すでにmain()関数をはじめとする幾つかの関数を見てきていますが、関数の内部は代表的なスコープです。またif式やwhile式などのブロックの内部もスコープになります。もっとも大きなスコープはプログラム全体です。スコープ内で宣言された変数は、そのスコープ内でのみ有効です。

スカラー型における所有権

 整数型や浮動小数点型といったスカラー型の変数は、変数間の代入において所有権は基本的に複製されます。これを「所有権の複製(コピー)」といいます。変数間の代入などにおいて所有権は複製されるので、値の所有者は常に1個でなければならないというルールは守られます。この動作を確かめてみましょう。なお、この回のサンプルはownershipsパッケージに作っていきます。

let x = 1;
let y = x;
println!("xは{}です。", x);             // 「xは1です。」
println!("yは{}です。", y);             // 「yは1です。」
src/bin/scalar.rsのソースコード

 何の変哲もないコードです。所有権という意識も不要ではないでしょうか。まず変数xが1で初期化され、続けて変数yが変数xの値で初期化されます。変数xは値として1を所有しているので、変数yも同じく1を所有することになります。しかし、所有権が複製されるので、この2つの1は別物ということになります。

 内部的な話をすると、スカラー型(この場合はi32型)である変数xも変数yも、値のためのメモリ領域はスタックと呼ばれるメモリ領域に確保され、変数yの初期化においては変数xの場所から値をコピーしてくるという動作になります。

スカラー型変数間の代入 スカラー型変数間の代入

【補足】スタックとヒープ

 スタック(stack)とは、プログラムが使用する一時的なメモリ領域です。関数の内部で宣言される変数は、基本的にスタック上に領域が確保されます。スタックを使う利点は、変数用のメモリコストが低いこと、解放も自動であることです。デメリットは、スタックの大きさは固定されている場合が多く、大きなデータの置き場所には向かず、使い切ってしまうとプログラムを異常終了させるしか手段がなくなるという点です。これを解決するのがヒープ(heap)です。ヒープとは摘み草の山という意味ですが、山(ヒープ)から大きな量の草(メモリ)を持ってきたり、山に草を返したり、山の大きさを変えることができるなど、スタックに比べ融通性に富みますが、反面獲得コストは高くなります。

文字列型における所有権

 文字列型(String型)も同様に見ていきましょう。String型をはじめとする非スカラー型の場合は、変数間の代入において所有権は複製でなく移動となります。これを「所有権の移動(ムーブ)」といいます。変数間の代入で所有権が移動するため、値の所有者は常に1個でなければならないというルールは守られます。しかしスカラー型とは異なった振る舞いをするようになります。これを確かめてみましょう。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。