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

use*_*855 4 error-handling backtrace rust

我如何开始Backtrace与 SNAFU 合作?我尝试过,但我只是得到空的回溯。文档似乎很少。

return Error::SampleError {
    msg: "foo".to_string(),
    backtrace: Backtrace::generate(),
};
Run Code Online (Sandbox Code Playgroud)

印刷

return Error::SampleError {
    msg: "foo".to_string(),
    backtrace: Backtrace::generate(),
};
Run Code Online (Sandbox Code Playgroud)

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

She*_*ter 6

让我们从这个最小的、可重现的示例开始:

\n\n
use snafu::Snafu;\n\n#[derive(Debug, Snafu)]\nenum Error {\n    SampleError { msg: String },\n}\n\ntype Result<T, E = Error> = std::result::Result<T, E>;\n\nfn alpha() -> Result<()> {\n    beta()\n}\n\nfn beta() -> Result<()> {\n    gamma()\n}\n\nfn gamma() -> Result<()> {\n    SampleError { msg: "foo" }.fail()\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

现在我们将snafu::Backtrace其导入并添加到我们的错误中,并命名它backtrace(如果您必须将其称为其他名称,请参阅控制回溯)。

\n\n
use snafu::{Snafu, Backtrace};\n\n#[derive(Debug, Snafu)]\nenum Error {\n    SampleError { msg: String, backtrace: Backtrace },\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果这是一个图书馆,那就是你应该停下来的地方。如果二进制文件认为回溯是值得的,那么您的错误现在可以选择启用回溯。这样做是因为 Rust 中的回溯尚未稳定,因此 SNAFU 必须与多种可能的实现兼容。

\n\n

如果您正在控制二进制文件,则需要决定如何实现回溯。通过功能标志选择三种主要实现:

\n\n
    \n
  • backtraces\xe2\x80\x94 提供不透明Backtrace类型
  • \n
  • backtraces-impl-backtrace-crate\xe2\x80\x94 使用第三方回溯包。snafu::Backtrace只是 的别名backtrace::Backtrace
  • \n
  • unstable-backtraces-impl-std\xe2\x80\x94 使用不稳定的标准库Backtracesnafu::Backtrace只是 的别名std::backtrace::Backtrace
  • \n
\n\n

一旦您选择了实现功能标志,请将其添加到您的 Cargo.toml 中:

\n\n
[dependencies]\nsnafu = { version = "0.6.3", features = ["backtraces"] }\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,您需要在程序的高层处理错误并获取回溯并将其打印出来。这使用了该ErrorCompat特征,我鼓励您以详细的方式使用该特征,以便稍后当它在标准库中稳定时更容易将其删除:

\n\n
use snafu::ErrorCompat;\n\nfn main() {\n    if let Err(e) = alpha() {\n        if let Some(bt) = ErrorCompat::backtrace(&e) {\n            println!("{:?}", bt);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
use snafu::Snafu;\n\n#[derive(Debug, Snafu)]\nenum Error {\n    SampleError { msg: String },\n}\n\ntype Result<T, E = Error> = std::result::Result<T, E>;\n\nfn alpha() -> Result<()> {\n    beta()\n}\n\nfn beta() -> Result<()> {\n    gamma()\n}\n\nfn gamma() -> Result<()> {\n    SampleError { msg: "foo" }.fail()\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
\n\n

您是对的,用户指南中没有对此进行彻底描述,我已经创建了一个问题来改进这一点。最相关的部分是关于功能标志的部分。

\n\n

SNAFU 存储库中有多个回溯测试,您可以查看:

\n\n\n