越界数组索引是否应该在Rust中产生错误或警告



我正在读《铁锈》一书,我遇到了这个例子:

fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;
let element = a[index];
println!("The value of element is: {}", element);
}

书中说运行cargo run后。。。

编译没有产生任何错误,但程序导致运行时错误,没有成功退出。

我不明白。我看到编译错误,即使通过cargo buildrustc src/main.rs进行编译,我也会看到错误。

在这个例子中它们是什么意思?为什么这不是编译错误,而是运行时错误?

编译器现在比以前更智能了,所以它会产生编译错误。

您需要更改代码,使其不太容易为编译器验证。例如:

fn main() {
let a = [1, 2, 3, 4, 5];
let index = a.len() + 1;
let element = a[index];
println!("The value of element is: {}", element);
}

上面的代码在当前版本(1.60(编译并恐慌。

此外,编译器通常只能证明数组([T; N](的边界访问,而不能证明切片和Vec的边界访问。

Rust在书中得到了更聪明的持续评估。有一个打开的拉取请求,将本章更新为以下内容:

如果您试图访问数组中超过数组末尾的元素,会发生什么?如果您将示例更改为以下代码,它将不会编译:

fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;
let element = a[index];
println!("The value of element is: {}", element);
}

使用cargo build构建此代码会产生以下结果:

$ cargo run
Compiling arrays v0.1.0 (file:///projects/arrays)
error: this operation will panic at runtime
--> src/main.rs:5:19
|
5 |     let element = a[index];
|                   ^^^^^^^^ index out of bounds: the len is 5 but the index is 10
|
= note: `#[deny(unconditional_panic)]` on by default
error: aborting due to previous error
error: could not compile `arrays`.
To learn more, run the command again with --verbose.

当编译器能够证明发生了无效的数组访问时,它将无法编译。然而,在某些情况下,编译不会产生任何错误,但程序本身会因运行时错误而失败,并且无法成功退出。

在运行时,当您尝试使用索引访问元素时,Rust将检查您指定的索引是否小于数组长度。如果索引大于或等于数组长度,Rust将死机。

这是Rust安全原则的第一个应用实例。在许多低级语言中,这种检查是不进行的,当您提供了不正确的索引时,可能会访问无效的内存。Rust通过不允许程序编译来保护您免受这种错误的影响,或者如果在编译时无法识别错误,它可能会在运行时死机,这将立即退出程序,而不是允许发生无效的内存访问。第9章详细讨论了Rust的错误处理。

相关内容

  • 没有找到相关文章

最新更新