【问题标题】:Accessing out of bound index in array in Rust - compile vs runtime error?在 Rust 中访问数组中的越界索引 - 编译与运行时错误?
【发布时间】:2020-12-20 19:59:19
【问题描述】:

我正在阅读 The 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 build 或rustc src/main.rs 进行编译,我也看到了错误。

this example 中的它们是什么意思?为什么这不是编译错误,而是运行时错误?

【问题讨论】:

  • 这看起来显然是错误的。我想知道编译器是否已更新为进行编译时边界检查,而书中的这一页从未更新过。
  • 程序在运行cargo build时编译成功。
  • @IbraheemAhmed 如果编译为库并且main 被推断为死代码,是的,编译器不会对死代码进行 const 分析。否则,构建会产生所描述的错误。
  • @kmdreko 哦,完全错过了。这应该是be reported

标签: rust


【解决方案1】:

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

您需要更改代码以便编译器更容易验证。例如:

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);
}

以上代码在当前版本出现恐慌。

【讨论】:

    【解决方案2】:

    自从本书编写以来,Rust 得到了更聪明的持续评估。有一个open pull request 将章节更新为以下内容:

    如果您尝试访问超出数组末尾的数组元素会发生什么?如果将示例更改为以下代码,将无法编译:

    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 的错误处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 2017-07-26
      • 2015-09-14
      • 1970-01-01
      • 2014-06-06
      • 2015-03-22
      相关资源
      最近更新 更多