[英]Is signed integer overflow in safe Rust in release mode considered as undefined behavior?
[英]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.