繁体   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