最終更新日時:
が更新

履歴 編集

実行時アサート

assert

実行時アサートには、BOOST_ASSERTマクロ、もしくはBOOST_ASSERT_MSGマクロを使用する。これらのマクロは、<boost/assert.hpp>ヘッダで定義される。

インデックス

式を検証する

式を検証するには、BOOST_ASSERTマクロを使用する。このマクロは引数として条件式をとる。条件式がtrueに評価される場合は検証成功となり、falseの場合は検証失敗と見なされる。

検証失敗時は、プログラムが異常終了する。

デフォルトでは、NDEBUG#defineされていない場合(デバッグモード)のみ検証が行われる。

#include <boost/assert.hpp>

int main()
{
    // 検証に成功するケース
    BOOST_ASSERT(1 == 1);

    // 検証に失敗するケース
    BOOST_ASSERT(1 != 1);
}

出力例:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Assertion failed!

Program: main.exe
File: main.cpp, Line 9

Expression: 1 != 1

メッセージ付きで式を検証する

検証失敗時にコンパイルエラーにエラーメッセージを出力するには、BOOST_ASSERT_MSGマクロを使用する。基本的な使い方はBOOST_ASSERTと同様で、第2引数にメッセージの文字列を取る。

#include <boost/assert.hpp>

int main(int argc, char* argv[])
{
    BOOST_ASSERT_MSG(argc > 1, "you must specify at least one option");
}

また、式を評価する必要が無く、該当箇所を通過した場合に単にデバッグ用途で無条件に落としたい場合、文字列を示すポインタの評価結果は常に真になることを利用して、イディオム的に以下のような書き方もできる。

#include <iostream>
#include <boost/assert.hpp>

int main(int argc, char* argv[])
{
    if (argc == 1 + 1) {
        std::cout << "option 1: " << argv[1] << std::endl;
    } else {
        BOOST_ASSERT(!"unknown extra option specified");
    }
}

これはNDEBUG#defineされているビルド(リリースビルド)では暗黙のうちに通過してしまいバグの原因となるので、あくまで簡易的なデバッグ用途に留めるべきである。

検証失敗時の動作をカスタマイズする

BOOST_ASSERTでの検証失敗時の動作をカスタマイズしたい場合は、以下の方法をとる:

  • <boost/assert.hpp>ヘッダをインクルードする前に、BOOST_ENABLE_ASSERT_HANDLER#defineする
  • boost名前空間にassertion_failed()関数を定義する

この方法をとることによって、検証失敗時に、自分で定義したassertion_failed()関数が呼ばれるようになる。この関数には、以下のパラメータが渡される:

  • 文字列化された式
  • 関数名(形式は環境依存)
  • ファイル名(__FILE__)
  • 行番号(__LINE__)

# define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/assert.hpp>
#include <fstream>
#include <cstdlib>

namespace boost {
    void assertion_failed(const char* expr, const char* function, const char* file, long line)
    {
        // ログに出力して、アプリケーションを異常終了させる
        std::ofstream log("log.txt", std::ios::out | std::ios::app);
        log << "Expression : " << expr << '\n'
            << "Function : " << function << '\n'
            << "File : " << file << '\n'
            << "Line : " << line << std::endl;
        std::abort();
    }
}

int main()
{
    BOOST_ASSERT(1 == 2);
}

出力例:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

log.txt:

Expression : 1 == 2
Function : int main()
File : C:\language\cpp\main.cpp
Line : 21

BOOST_ASSERT_MSGの場合は、以下のようにする:

  • <boost/assert.hpp>ヘッダをインクルードする前に、BOOST_ENABLE_ASSERT_HANDLER#defineする
  • boost名前空間にassertion_failed_msg()関数を定義する

これによって、BOOST_ASSERT_MSGでの検証失敗時に、自分で定義したassertion_failed_msg()関数が呼ばれるようになる。この関数には、以下のパラメータが渡される:

  • 文字列化された式
  • メッセージ
  • 関数名(形式は環境依存)
  • ファイル名(__FILE__)
  • 行番号(__LINE__)

# define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/assert.hpp>
#include <fstream>
#include <cstdlib>

namespace boost {
    void assertion_failed_msg(const char* expr, const char* msg, const char* function,
                              const char* file, long line)
    {
        // ログに出力して、アプリケーションを異常終了させる
        std::ofstream log("log.txt", std::ios::out | std::ios::app);
        log << "Expression : " << expr << '\n'
            << "Message : " << msg << '\n'
            << "Function : " << function << '\n'
            << "File : " << file << '\n'
            << "Line : " << line << std::endl;
        std::abort();
    }
}

int main()
{
    BOOST_ASSERT_MSG(1 == 2, "1 is not 2");
}

出力例:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

log.txt:

Expression : 1 == 2
Message : 1 is not 2
Function : int main()
File : C:\language\cpp\main.cpp
Line : 22

documented boost version is 1.52.0