使用SNAFU时如何查看错误的回溯?

问题描述 投票:0回答:1

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

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

打印

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

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

error-handling rust backtrace
1个回答
1
投票

让我们以此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()
}

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

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

use snafu::{Snafu, Backtrace};

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

如果这是一个图书馆,那是您应该停止的地方。如果binary认为值得使用回溯功能,则您的错误现在将可选地启用回溯功能。之所以这样做,是因为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存储库中对回溯进行多种测试:

© www.soinside.com 2019 - 2024. All rights reserved.