[ C++で開発 ]

アサーション

プログラムの検証を行う際のツールの1つで、プログラム時の仮定が満たされないことを検出するための機構です。例えば、ある関数が引数に繰り返し回数を取るときに、設計上は1回以上100回以下を想定して実装していたとします。引数の型がsigned intであった場合、呼び出し側の誤りによって負の値や100を越えた値が渡されることがあります。引数の範囲をアサーションでチェックしていれば、誤りは即座に判明します。しかし、チェックがなければ誤りはずっと後の処理まで次々と伝播し、気がついたときにはとんでもない被害をもたらすかもしれません註1

ANSI Cのassert

アサーションは、ANSI C規格で定められています。簡単なサンプルを示します。

simple_assert.c
#include <stdio.h>
#include <assert.h>

void test_assert(int times)
{
  assert(0 < times && times <= 100);
  printf("processing test_assert: times = %d\n", times);
}

int main(int argc, char *argv[])
{
  int num = 100;

  test_assert(num);
  num = -1;
  test_assert(num);

  return 0;
}

assertの()の中に記述した式が偽(ゼロ)の場合、エラー表示後プログラムを強制終了します。

このassertはマクロで定義されており、NDEBUGシンボルが定義されているとassertの処理は無効となります。

GCCでのコンパイル・実行例

assertを有効にするコンパイル

work$ gcc -o simple_assert simple_assert.c
work$ ./simple_assert
processing test_assert: times = 100
assertion "0 < times && times <= 100" failed: file "simple_assert.c", line 6
Aborted (core dumped)
work$

アサーションが検出されると、アサーションの式と発生したファイル名、行番号をエラー表示してコアダンプします。

assertを無効にするコンパイル

work$ gcc -DNDEBUG -o simple_assert simple_assert.c
work$ ./simple_assert
processing test_assert: times = 100
processing test_assert: times = -1
work$

Visual C++でのコンパイル・実行例

assertを有効にするコンパイル

Visual C++では、デバッグビルドをするとassertが有効になります。(NDEBUGが定義されない)

assertが検出されると、コンソールにアサーションの式、ファイル名、行番号をエラー表示します。また、エラーダイアログが表示されます。(以下の図)

assertを無効にするコンパイル

Visual C++では、リリースビルドをするとassertが無効になります。(NDEBUGが定義される)

Visual C++固有のアサーション

Cランタイムライブラリ

_ASSERTおよび_ASSERTEマクロ

ヘッダファイル<crtdbg.h>をインクルードします。

_DEBUGマクロが定義されている条件でコンパイルされた場合に有効となります。

_ASSERTは、評価式が偽のときにデフォルトではデバッグダイアログを表示します。
_ASSERTEは、評価式が偽のときにデフォルトではデバッグダイアログを表示し、ダイアログには偽となった評価式を表示します。

アサーションの表示先を変更するには、_CrtSetReportMode関数を使用します。デバッグダイアログの他にはデバッガ、ファイル、ストリームに出力を行うことができます。

MFC

ASSERTマクロ

VERIFYマクロ

注記

註1
『アメリカ海軍の誘導ミサイル巡洋艦ヨークタウンで起こった事件に関する記事が記載されている。ある乗組員がデータ値として間違ってゼロを入力してしまい、その結果ゼロによる除算エラーが発生した。そしてエラーが次々に伝播し、最終的には艦の推進システムをダウンさせてしまった。プログラムが入力の有効性チェックをさぼたおかげで、ヨークタウンは海上で2時間立ち往生するはめになったのだ』(「プログラミング作法」Brian W.Kernighan、Rob Pike著、福崎俊博訳、アスキー出版、p.196より引用)