2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rust: anyhowを使ってビルトインエラーにバックトレース情報を付加する方法

Last updated at Posted at 2023-05-20

この記事では、Rustのビルトインエラーにバックトレース情報を付加する方法を解説します。ここでは、anyhow クレートを使用してその問題を解決する方法について説明します。

ビルトインエラーの問題点

Rustのビルトインエラーは便利ですが、「デフォルトではバックトレース情報が付加されていません」という問題点があります。これにより、エラーの原因を特定するのが困難になる場合があります。例えば、次のようなコードがあります。

use std::num::ParseIntError;

fn main() {
    let err: Result<(), ParseIntError> = stack1();
    eprintln!("{err:?}");
}

fn stack1() -> Result<(), ParseIntError> {
    stack2()?;
    Ok(())
}

fn stack2() -> Result<(), ParseIntError> {
    parse_int()?;
    Ok(())
}

fn parse_int() -> Result<i32, ParseIntError> {
    "invalid".parse::<i32>()
}

このコードを実行すると、エラーメッセージが次のように表示されます。

Err(ParseIntError { kind: InvalidDigit })

この結果から、エラーが ParseIntError であることはわかりますが、どの関数で問題が発生したのかは明らかになりません。

解決策: anyhowクレートを使用する

エラーが発生したスタックフレーム情報を含むバックトレースがあれば、開発者はエラーの原因を特定しやすくなります。

anyhow クレートは、エラー処理を簡単にするためのライブラリで、バックトレース情報を付加する機能も含まれています。以下のステップに従って、上記の問題を解決していきます。

ステップ1: 依存関係を追加する

Cargo.toml に以下の依存関係を追加します。

[dependencies]
anyhow = { version = "1.0.70", features = ["backtrace", "std"] }

anyhowの backtracestd のfeaturesを有効にすることで、バックトレース情報をサポートし、エラーハンドリングで標準エラーからanyhow::error:Errorへの変換も手軽に扱えるようになります。

ステップ2: コードにあてはめる

以下のコードスニペットは、anyhow を使用してバックトレースを含むエラーを生成する方法を示しています。

fn main() {
    let err: Result<(), anyhow::Error> = stack1();
    eprintln!("{:#?}", err);
}

fn stack1() -> Result<(), anyhow::Error> {
    stack2()?;
    Ok(())
}

fn stack2() -> Result<(), anyhow::Error> {
    parse_int()?;
    Ok(())
}

fn parse_int() -> Result<i32, anyhow::Error> {
    "invalid".parse::<i32>().map_err(|e| e.into())
}

ライブラリエラーを返す可能性がある関数の呼び出しは、?でプロパゲーションする前に into() を使って anyhow::Error に変換することで、バックトレース情報が適切に付加されます。

ステップ3: バックトレースを表示する

バックトレースを表示するには、RUST_BACKTRACE 環境変数を1に設定してプログラムを実行します。これにより、バックトレース情報が有効になります。

RUST_BACKTRACE=1 cargo run

これにより、以下のようなバックトレースが表示されます。

Err(invalid digit found in string

Stack backtrace:
    ...
   8: parse_int
             at ./src/main.rs:20:5
   9: stack2
             at ./src/main.rs:12:5
  10: stack1
             at ./src/main.rs:7:5
  11: main
             at ./src/main.rs:2:42
    ...

この結果から、エラーが parse_int 関数で発生したことがわかります。また、stack1stack2 の関数もバックトレースに表示されています。

まとめ

この記事では、anyhow を使って Rust のビルトインエラーにバックトレース情報を付加する方法を紹介しました。これにより、開発者がエラーの原因を特定しやすくなり、デバッグが容易になります。

関連

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?