【C++】std::error_code と system_error | OSレベルのエラーを扱う方法

目次

はじめに

C++で、ファイルが存在しない、ネットワークがダウンしている、アクセス権がない、といったOSが原因のエラーを処理する場合、単なる int のエラーコードを返すだけでは、エラーの原因が何であるかが分かりにくくなります。

C++11では、このようなプラットフォーム依存のエラーを、移植性の高い、統一的な方法で扱うための仕組みとして、<system_error> ヘッダーが導入されました。

  • std::error_code: エラーコードのとそのカテゴリ(どの種類のエラーか)をペアで保持する。
  • std::system_error: error_codeをラップする例外クラス

この記事では、これらのクラスを使って、OSレベルのエラーを型安全にハンドリングする方法を解説します。


【前提】C++11とは?

C++11は、2011年に正式化されたC++言語のメジャーアップデート版です。<system_error>ライブラリはこのC++11で導入されたため、利用するにはC++11以降に対応したコンパイラが必要です。


error_code / system_error を使ったサンプルコード

このコードは、データベースへの接続をシミュレートする関数を定義します。接続に失敗した場合、エラーの種類に応じて error_code を設定し、system_error 例外をスローします。

完成コード

#include <iostream>
#include <system_error> // error_code, system_error
#include <string>

using namespace std;

// データベース接続をシミュレートする関数
void connect_to_database(bool should_fail) {
    if (should_fail) {
        // 1. errc列挙体から、エラーコードを作成
        error_code ec = make_error_code(errc::connection_refused);
        
        // 2. error_codeをラップしたsystem_error例外をスロー
        throw system_error(ec, "データベースに接続できませんでした。");
    } else {
        cout << "データベースへの接続に成功しました。" << endl;
    }
}

int main() {
    // 3. system_error例外をcatchする
    try {
        connect_to_database(true); // 失敗するケース
    }
    catch (const system_error& e) {
        // 4. エラー情報を取得
        const error_code& ec = e.code();
        
        cout << "エラーが発生しました。" << endl;
        cout << "  詳細: " << e.what() << endl;
        cout << "  カテゴリ: " << ec.category().name() << endl;
        cout << "  エラー値: " << ec.value() << endl;
        cout << "  メッセージ: " << ec.message() << endl;
    }
    
    return 0;
}

コードの解説

1. std::error_code

error_code は、エラーコードのint)と、その値がどのような種類のエラーなのかを示すカテゴリerror_categoryへのポインタ)をペアで保持します。

error_code ec = make_error_code(errc::connection_refused);

  • std::errc: <system_error> で定義されている、移植性の高い標準的なエラー条件を表す列挙型です。errc::network_down(ネットワークダウン)や errc::permission_denied(アクセス権なし)などがあります。
  • make_error_code(): errc の列挙子から、対応する error_code オブジェクトを簡単に作成するためのヘルパー関数です。

2. std::system_error

system_error は、std::exceptionから派生した例外クラスです。 throw system_error(ec, "追加メッセージ");

  • 第1引数: エラーの原因を示す error_code オブジェクト。
  • 第2引数(オプション): エラーに関する、より具体的な文脈を示す文字列。

3. try-catch ブロック

main関数では、system_error例外を catch しています。これにより、OSレベルのエラーが発生してもプログラムがクラッシュせず、エラー情報を分析して適切な対応をとることができます。

4. エラー情報の取得

catchブロックで捕捉したsystem_errorオブジェクト e から、様々な情報を取得できます。

  • e.code(): 元となった error_code オブジェクトを返します。
  • e.what(): system_error のコンストラクタで渡された追加メッセージと、error_code のメッセージを組み合わせた、詳細なエラー説明文字列を返します。
  • ec.message(): error_code に対応する、プラットフォーム標準のエラーメッセージ(例: "Connection refused")を返します。

まとめ

今回は、C++11の <system_error> ライブラリを使って、OSレベルのエラーを扱うための標準的な方法を解説しました。

  • std::errc: 移植性の高い、共通のエラー条件を表す列挙型。
  • std::error_code: エラーコードの値とカテゴリを保持する。
  • std::system_error: error_code をラップする例外クラス。

この仕組みを使うことで、ファイル操作やネットワーク通信などで発生しうる様々なプラットフォーム依存のエラーを、統一的で型安全な方法でハンドリングすることができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次