🧊

Rustの整数オーバーフローは、デフォルトではdebugビルドでのみパニックする

こんなんどこで学ぶんや!ってなったやつ。

再現コード

実際に遭遇したのとは違うけど、

fn main() {
    let max = u8::MAX;
    println!("MAX: {max} | MAX+1: {}", max + 1);
}

こういうコードを用意し、

cargo run

した場合、

thread 'main' panicked at src/main.rs:3:40:
attempt to add with overflow

と表示される。

考えてみれば、JSと違って扱える型やその最大値が決まってるならば、それを踏み越えたときに問題になるのはまあわかる。

が、

cargo run -r

した場合は、

MAX: 255 | MAX+1: 0

なんとpanicしない!

overflow-checks

https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow https://doc.rust-lang.org/cargo/reference/profiles.html#overflow-checks

リリースビルドではこの設定がOFFになってるらしく、有効にする場合は、

[profile.release]
overflow-checks = true

これをCargo.tomlに追記するか、同等のフラグを渡す。

そもそも

いやいやパニックは困る・・・という場合。

match max.checked_add(1) {
    Some(p1) => println!("MAX: {max} | MAX+1: {p1}"),
    None => println!("MAX: {max} | MAX+1: Overflow"),
}

というように、安全に計算できるやつがある。

  • checked_add()
  • checked_sub()
  • checked_mul()
  • etc…

もちろんu8だけじゃなくあらゆる数値型で使えるようだった。

https://doc.rust-lang.org/1.80.1/src/core/num/uint_macros.rs.html#457

ほかにも

溢れたときの挙動をどうしたいかによって、他にも派生形が使える。

勉強になった。