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

nhaq1z21  于 2023-01-30  发布在  其他
关注(0)|答案(3)|浏览(154)

在编写使用Result类型的代码时,您可能希望用户和开发人员有不同的行为。

  • 当编写一个能够优雅地处理错误的应用程序时,使用Result是很好的。
  • 在开发过程中,您可能希望“捕获”错误,以查看是哪行代码创建了错误,或者在创建Err值时获得堆栈跟踪。

如果你犯了一个独特的错误,那么搜索它并不难,但是如果这个错误来自标准库,那么这个错误可能是非常一般的。
例如,如果不手动将每个file.read()?更改为file.read().unwrap(),就不可能知道哪个read命令导致了意外的文件结束。
有没有一种方便的方法可以从Result获得堆栈跟踪?
一个弱但可行的解决方案可能是创建一个用于阅读的宏read_in_release_unwrap_in_debug!(file, data) ...但这感觉非常笨拙。
我有一个文件读取器,有很多read调用,其中一个失败了。我不确定是哪个。在运行时,我想把结果推回调用者。为了调试,我想停止失败的read调用,或者让我知道它的行号。

3b6akqbq

3b6akqbq1#

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

RUST_BACKTRACE=1 cargo +nightly run

This is the tracking issue for stabilisationa PR to stabilise it。看起来在稳定之前是否需要在no_std中工作或类似的问题上存在一些分歧。

wdebmtf2

wdebmtf22#

结果本身没有任何回溯信息,但您可以将其添加到自定义错误类型中。
error_chain crate(不幸的是它是no longer maintained)是一个为您生成错误类型的示例,当设置RUST_BACKTRACE环境变量时,您可以免费获得回溯生成。
您也可以直接使用backtrace库并自己完成。

rqmkfv5c

rqmkfv5c3#

我用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!())?;

相关问题