如何追踪错误结果的原因?

ide*_*n42 7 error-handling rust

编写使用Result类型的代码时,您可能需要为用户和开发人员提供不同的行为.

  • 在编写一个优雅地处理错误的应用程序时,使用起来很不错Result.
  • 在开发过程中,您可能希望"捕获"错误以查看代码行创建错误或Err在创建值时获取堆栈跟踪.

如果您发出唯一错误,则搜索它并不困难,但如果错误来自标准库,则错误可能非常通用.

例如,它是不可能知道哪个read命令造成的意外结束的文件,而不手动更改每file.read()?file.read().unwrap().

有没有一种方便的方法来获取堆栈跟踪Result

一个弱但可行的解决方案可能是制作阅读宏,read_in_release_unwrap_in_debug!(file, data)......但这感觉非常尴尬.


我有一个文件阅读器有很多read电话,一个失败.我不确定哪个.在运行时,我想将结果推回给调用者.对于调试,我希望失败的读取调用停止或以某种方式让我知道它的行号.

Chr*_*son 7

结果本身没有任何回溯信息,但您可以将其添加到自定义错误类型.

error_chain箱子是为您生成一个错误类型,其中,当你回溯代免费的例子RUST_BACKTRACE环境变量设置.

您也可以直接使用backtrace库并自己完成.


Tim*_*mmm 6

如果你使用,anyhow你可以免费得到这个!问题是您需要每晚使用并启用环境变量:

RUST_BACKTRACE=1 cargo +nightly run
Run Code Online (Sandbox Code Playgroud)

这是稳定的跟踪问题,以及稳定它的 PR。看起来在稳定之前是否需要在 no_std 中工作或类似的事情存在一些分歧。

  • 在带有“anyhow”“1.0.66”的 Rust“1.65”上,我需要在“Cargo.toml”中启用“backtrace”功能。IE。`无论如何= {版本=“1.0.66”,功能=[“回溯”]}` (6认同)
  • 根据链接的 PR,它现在看起来很稳定。 (4认同)

com*_*lip 5

我用easy-error crate 解决了这个要求,而error-chain crate 也很好。

使用中定义的Resulteasy-error作为返回类型,然后使用context方法转换其他Result类型。

最重要的是将信息传递给context带有行号的方法。

use easy_error::{Result, ResultExt};
use std::path::PathBuf;

fn test_open() -> Result<()> {
    let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    p.push("resources/test/songs.json");
    File::open(p).context(format!("{}:{}", file!(), line!()))?;
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

format!("{}:{}", file!(), line!())为了避免一直打字,定义一个宏:

#[macro_export]
macro_rules! code_loc {
    () => {
        format!("{}:{}", file!(), line!())
    };
}
Run Code Online (Sandbox Code Playgroud)

最后代码将是:

File::open(p).context(code_loc!())?;
Run Code Online (Sandbox Code Playgroud)