簡體   English   中英

為什么 Rust 在 --release 中執行 integer 溢出檢查?

[英]Why does Rust perform integer overflow checks in --release?

我有這段簡單的代碼:

let val: u8 = 255 + 1;
println!("{}", val);

這里說如果使用--release標志運行這樣的代碼將正常編譯。

我通過cargo run --release運行這段代碼,我仍然看到檢查:

error: this arithmetic operation will overflow
 --> src/main.rs:2:19
  |
2 |     let val: u8 = 255 + 1;
  |                   ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
  |
  = note: `#[deny(arithmetic_overflow)]` on by default

error: could not compile `rust-bin` due to previous error

我錯過了什么嗎?

這本書有點不精確。 在調試和發布模式下都不允許溢出,只是發布模式出於性能原因忽略了運行時檢查(用溢出替換它們,CPU 通常會這樣做)。 Static 檢查不會被刪除,因為它們不會影響生成代碼的性能。 例如,這在發布模式下打印 0 並在調試1中出現恐慌:

let x: u8 = "255".parse().unwrap();
let val: u8 = x + 1;
println!("{}", val);

您可以使用#[allow(arithmetic_overflow)]禁用編譯時檢查。 例如,這也會在發布模式下打印 0 並在調試時出現恐慌:

#[allow(arithmetic_overflow)]
let val: u8 = 255 + 1;
println!("{}", val);

正確的做法是不依賴於發布模式的這種行為,而是告訴編譯器你想要什么。 這在調試和發布模式下都打印 0:

let val: u8 = 255u8.wrapping_add(1);
println!("{}", val);

1該示例使用"255".parse() ,因為令我驚訝的是, let x = 255u8; let val = x + 1; let x = 255u8; let val = x + 1; 不編譯- 換句話說,rustc 不僅可以防止常量算術溢出,而且還可以證明它發生的任何其他地方。 更改顯然是在 Rust 1.45 中進行的,因為它是在Rust 1.44 和更早版本中編譯的。 由於它破壞了先前編譯的代碼,因此該更改在技術上是向后不兼容的,但可能破壞了足夠少的實際 crate,以至於它被認為是值得的。 令人驚訝的是, "255".parse::<u8>() + 1很可能在以后的版本中成為編譯時錯誤。

在您的代碼中,編譯器能夠檢測到問題。 這就是為什么即使在發布模式下它也會阻止它。 在許多情況下,編譯器無法檢測或防止錯誤。

舉個例子,假設你有這樣的代碼:

let a = b + 5;

假設b的值來自數據庫、用戶輸入或其他一些外部來源。 在這種情況下,實際上不可能防止溢出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM