如何使用SNAFU获得Backtrace?我试过了,但是回溯到空了。该文件似乎很少。

return Error::SampleError {
    msg: "foo".to_string(),
    backtrace: Backtrace::generate(),
};

打印

SampleError { msg: "foo", backtrace: Backtrace(()) }

这是从调用堆栈中非常深的函数抛出的。

最佳答案

让我们从minimal, reproducible example开始:

use snafu::Snafu;

#[derive(Debug, Snafu)]
enum Error {
    SampleError { msg: String },
}

type Result<T, E = Error> = std::result::Result<T, E>;

fn alpha() -> Result<()> {
    beta()
}

fn beta() -> Result<()> {
    gamma()
}

fn gamma() -> Result<()> {
    SampleError { msg: "foo" }.fail()
}

请注意,它使用上下文选择器SampleErrorfail方法,而不是直接使用enum变体来构造错误。

现在,我们导入snafu::Backtrace并将其添加到我们的错误中,将其命名为backtrace(如果必须调用其他名称,请参见controlling backtraces)。
use snafu::{Snafu, Backtrace};

#[derive(Debug, Snafu)]
enum Error {
    SampleError { msg: String, backtrace: Backtrace },
}

如果这是一个图书馆,那是您应该停止的地方。如果二进制认为值得使用回溯,则现在您的错误将有选择地启用回溯。之所以这样做,是因为Rust中的回溯作用尚未稳定,因此SNAFU必须与多种可能的实现兼容。

如果要控制二进制文件,则需要决定如何实现回溯。功能标记选择了三种主要实现:
  • backtraces —提供不透明的Backtrace类型
  • backtraces-impl-backtrace-crate-使用第三方backtrace条板箱。 snafu::Backtrace只是backtrace::Backtrace的别名。
  • unstable-backtraces-impl-std —使用不稳定的标准库Backtracesnafu::Backtrace只是std::backtrace::Backtrace的别名。

  • 选择实现功能标志后,将其添加到您的Cargo.toml中:
    [dependencies]
    snafu = { version = "0.6.3", features = ["backtraces"] }
    

    然后,您将需要在程序中某个较高的位置处理错误,并获取回溯并打印出来。这使用了ErrorCompat特性,我建议您以冗长的方式使用它,以便在标准库中将其稳定后,以后再将其删除更容易:
    use snafu::ErrorCompat;
    
    fn main() {
        if let Err(e) = alpha() {
            if let Some(bt) = ErrorCompat::backtrace(&e) {
                println!("{:?}", bt);
            }
        }
    }
    

       0: backtrace::backtrace::trace_unsynchronized
       1: backtrace::backtrace::trace
       2: backtrace::capture::Backtrace::create
       3: backtrace::capture::Backtrace::new
       4: <backtrace::capture::Backtrace as snafu::GenerateBacktrace>::generate
       5: so::SampleError<__T0>::fail
       6: so::gamma
       7: so::beta
       8: so::alpha
       9: so::main
      10: std::rt::lang_start::{{closure}}
      11: std::panicking::try::do_call
      12: __rust_maybe_catch_panic
      13: std::rt::lang_start_internal
      14: std::rt::lang_start
      15: main
    

    免责声明:我是SNAFU的主要作者。

    您是对的,在the user's guide中没有对此进行详细描述,我已经创建了an issue to improve that。最相关的部分是有关feature flags的部分。

    您可以在SNAFU存储库中对回溯进行多种测试:
  • backtrace-shim
  • backtraces-impl-backtrace-crate
  • backtraces-impl-std
  • 关于error-handling - 使用SNAFU时如何查看错误的回溯?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60943851/

    10-10 13:58