Code Fix

初級

index out of bounds パニックの原因と直し方

存在しない添字でVecや配列にアクセスすると、コンパイルは通りますが実行時にパニックしてプログラムが異常終了します。

エラーメッセージの読み方

thread 'main' panicked at main.rs:3:26:
main.rs
ファイル名
3
行番号 — 実際にクラッシュした行
26
列番号
panicked
パニック — 実行時に回復不能な状態になったことを示します。tryやResultで捕まえない限り、そのままプロセスが終了します
index out of bounds: the len is 3 but the index is 5
詳細メッセージ — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  fn main() {
 2      let scores = vec![85, 90, 78];
 3      println!("{}", scores[5]);
                              ^
 4  }
thread 'main' panicked at main.rs:3:26: index out of bounds: the len is 3 but the index is 5

scoresの要素数は3なので、有効な添字は0から2までです。5は範囲外なのでパニックします。

直し方: 5 を 1 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fn main() {
 2      let prices = vec![100, 250, 300];
 3      println!("{}", prices[10]);
                               ^
 4  }
thread 'main' panicked at main.rs:3:26: index out of bounds: the len is 3 but the index is 10

添字が変数や計算結果の場合、コンパイラは範囲を事前にチェックできません。範囲外アクセスは実行時にしか分かりません。

直し方: 10 を 0 にします。

この問題を解いてみる →

パターン3

 1  fn main() {
 2      let temps = vec![36, 37, 38, 39];
 3      println!("{}", temps[8]);
                             ^
 4  }
thread 'main' panicked at main.rs:3:25: index out of bounds: the len is 4 but the index is 8

要素数ちょうどの添字(この場合4)も範囲外です。最後の要素の添字は要素数より1小さい値になります。

直し方: 8 を 3 にします。

この問題を解いてみる →

パターン4

 1  fn main() {
 2      let ages = vec![20, 25, 30];
 3      println!("{}", ages[6]);
                            ^
 4  }
thread 'main' panicked at main.rs:3:24: index out of bounds: the len is 3 but the index is 6

Vecの範囲外アクセスは、C言語のように未定義動作にはならずパニックとして安全に検出されます。

直し方: 6 を 2 にします。

この問題を解いてみる →

パターン5

 1  fn main() {
 2      let counts = vec![5, 10, 15, 20, 25];
 3      println!("{}", counts[9 ]);
                               ^
 4  }
thread 'main' panicked at main.rs:3:26: index out of bounds: the len is 5 but the index is 9

要素数を勘違いしていると、範囲外の添字を指定してしまいパニックの原因になります。

直し方: 9 を 4 にします。

この問題を解いてみる →

よくある誤解

「範囲外にアクセスしてもコンパイラが事前に止めてくれるはず」という思い込みは誤りです。添字が変数の場合、境界チェックは実行時にしか行えないため、コンパイルは通ってしまいます。

実務での勘所

Rustは範囲外アクセスに対して2つの異なる道具を用意しています。[]による添字アクセスは「その添字は必ず有効なはず」と確信している場面向けで、もし間違っていればすぐにパニックさせて問題を顕在化させます。get(index)はOption<&T>を返し、範囲外かもしれない可能性を型として受け止めて、Noneの場合の処理を呼び出し側に書かせる設計です。「確実なら[]、不確実ならget」という使い分けが、Rustの安全性と簡潔さの両立の仕方です。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)