RustはC/C++のパフォーマンスを維持しながら、コンパイル時にメモリ安全性を保証するシステムプログラミング言語です。ガベージコレクタなしにこれを実現する核心にある所有権(Ownership)システムを理解しましょう。
なぜRustなのか?
MicrosoftとGoogleの研究によると、C/C++プログラムのセキュリティ脆弱性の70%以上がメモリ関連のバグ(use-after-free、バッファオーバーフロー、ヌルポインタ逆参照)に起因しています。Rustはこの問題をランタイムではなくコンパイル時に根本的に防ぎます。
- C/C++レベルのパフォーマンス:ゼロコスト抽象化(Zero-cost Abstraction)
- メモリ安全性:GCなしでメモリリーク・ダングリングポインタを防止
- スレッド安全性:コンパイラがデータ競合を事前に防止
- モダンなエコシステム:Cargoパッケージマネージャ、豊富な標準ライブラリ
核心概念:所有権(Ownership)
Rustのすべてのメモリ安全性は、3つの所有権ルールから始まります。
- すべての値には一つの所有者(owner)がいる
- 所有者は同時に一人だけ存在できる
- 所有者がスコープを外れると、値は自動的に解放(drop)される
fn main() {
let s1 = String::from("hello"); // s1が所有者
let s2 = s1; // 所有権がs2に移動(move)
// println!("{}", s1); // コンパイルエラー!s1はもう無効
println!("{}", s2); // OK
} // s2がスコープを外れるとメモリが自動解放
借用(Borrowing)と参照(Reference)
所有権を移転せずに値を使用するには参照(&)を使います。これを借用と呼びます。
fn calculate_length(s: &String) -> usize { // sは参照(借用)
s.len()
} // sがスコープを外れても元の値は解放されない
fn main() {
let s = String::from("hello");
let len = calculate_length(&s); // 参照を渡す
println!("長さは{}です", len); // sはまだ有効
}
可変参照と借用チェッカー
Rustの借用チェッカー(Borrow Checker)は2つのルールを強制します。
- 複数の不変参照(&T)は同時に許可される
- 同時に一つの可変参照(&mut T)のみ許可(不変参照との共存不可)
fn main() {
let mut s = String::from("hello");
let r1 = &s; // 不変参照1
let r2 = &s; // 不変参照2 - OK
// let r3 = &mut s; // エラー!不変参照が生きている間は可変参照不可
println!("{} {}", r1, r2);
let r3 = &mut s; // これならOK
r3.push_str(" world");
}
ライフタイム(Lifetime)
ライフタイムは参照が有効なスコープを明示する構文です。コンパイラが大部分を推論しますが、複数の参照が関係する場合は明示が必要です。
// 'aはライフタイムパラメータ:xとyのうち短い方の寿命で戻り値の寿命を決定
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
実践:Rustを学ぶべき場面
Rustはすべての状況に最適とは限りません。以下の基準で導入を検討してください。
- 適している:システムプログラミング、組み込み、CLIツール、WebAssembly、高性能APIサーバー
- 慎重に:素早いプロトタイピング、小規模スクリプト、チームのRust経験不足