Code Fix

中級

byte index is not a char boundary パニックの原因と直し方

Rustの文字列はUTF-8のバイト列として保持されており、日本語のようなマルチバイト文字の途中の位置でスライスしようとするとパニックします。文字単位で扱いたい場合はcharsなどのイテレータを使う必要があります。

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

thread 'main' panicked at main.rs:3:19:
main.rs
ファイル名
3
行番号 — 実際にクラッシュした行
19
列番号
panicked
パニック — 実行時に回復不能な状態になったことを示します。tryやResultで捕まえない限り、そのままプロセスが終了します
byte index 1 is not a char boundary; it is inside 'こ' (bytes 0..3) of `こんにちは`
詳細メッセージ — どの値が問題だったか

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

パターン1

 1  fn main() {
 2      let s = String::from("こんにちは");
 3      let slice = &s[0..1];
                          ^
 4      println!("{}", slice);
 5  }
thread 'main' panicked at main.rs:3:19: byte index 1 is not a char boundary; it is inside 'こ' (bytes 0..3) of `こんにちは`

日本語の1文字はUTF-8で3バイトです。バイト境界の途中である1や2を指定するとパニックします。

直し方: 13 にします。

この問題を解いてみる →

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

パターン2

 1  fn main() {
 2      let s = String::from("ありがとう");
 3      let slice = &s[0..2];
                          ^
 4      println!("{}", slice);
 5  }
thread 'main' panicked at main.rs:3:19: byte index 2 is not a char boundary; it is inside 'あ' (bytes 0..3) of `ありがとう`

英語の感覚で1文字ずつバイト数を数えると、マルチバイト文字の途中を指してしまいます。

直し方: 23 にします。

この問題を解いてみる →

パターン3

 1  fn main() {
 2      let s = String::from("すし");
 3      let slice = &s[0..1];
                          ^
 4      println!("{}", slice);
 5  }
thread 'main' panicked at main.rs:3:19: byte index 1 is not a char boundary; it is inside 'す' (bytes 0..3) of `すし`

文字数で数えたい場合は、バイトのスライスではなくcharsイテレータを使う必要があります。

直し方: 13 にします。

この問題を解いてみる →

パターン4

 1  fn main() {
 2      let s = String::from("ねこ");
 3      let slice = &s[0..2];
                          ^
 4      println!("{}", slice);
 5  }
thread 'main' panicked at main.rs:3:19: byte index 2 is not a char boundary; it is inside 'ね' (bytes 0..3) of `ねこ`

バイト境界でない位置を指定した瞬間に、Rustはその場でパニックして誤ったスライスを防ぎます。

直し方: 23 にします。

この問題を解いてみる →

パターン5

 1  fn main() {
 2      let s = String::from("さくら");
 3      let slice = &s[0..1];
                          ^
 4      println!("{}", slice);
 5  }
thread 'main' panicked at main.rs:3:19: byte index 1 is not a char boundary; it is inside 'さ' (bytes 0..3) of `さくら`

文字列のバイト長とその文字列が何文字かは、マルチバイト文字を含む限り一致しません。

直し方: 13 にします。

この問題を解いてみる →

よくある誤解

「文字列のスライスは英語と同じように1文字=1バイトとして数えられるはず」という思い込みは誤りです。UTF-8ではマルチバイト文字の内部にバイト境界があり、その途中を指定するとパニックします。

まとめ

byte index is not a char boundary パニックの原因と直し方は中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

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