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

时间:2017-02-16 13:48:07

标签: error-handling rust

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

  • 在编写优雅处理错误的应用程序时,最好使用Result
  • 在开发过程中,您可能希望“捕获”错误,以查看代码行创建错误或在创建Err值时获取堆栈跟踪。

如果你发出一个独特的错误,那么搜索它并不困难,但如果错误来自标准库,那么错误可能非常普遍。

例如,如果不手动将每个read更改为file.read()?,则无法知道哪个file.read().unwrap()命令导致意外的文件结尾。

是否有方便的方法从Result获取堆栈跟踪?

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

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

3 个答案:

答案 0 :(得分:7)

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

error_chain crate是一个为您生成错误类型的示例,当设置RUST_BACKTRACE环境变量时,您可以免费获得回溯生成。

您也可以直接使用backtrace库并自行完成。

答案 1 :(得分:1)

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

RUST_BACKTRACE=1 cargo +nightly run

This is the tracking issue for stabilisationa PR to stabilise it。对于是否需要在稳定之前在no_std中工作还是类似的问题,似乎存在一些分歧。

答案 2 :(得分:0)

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

使用easy-error中定义的Result作为返回类型,然后使用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(())
}

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

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

最后的代码将是:

File::open(p).context(code_loc!())?;