朝からアサーションを使ってみる

アサーションというのはassert()のことで、プログラム中で「これこれの変数は〜だと思う。違ったらエラーを出してくれ」と指示するデバッグ用のC言語標準の関数(正確にいうとマクロなのだが)である。これを使うと、デバッグ効率が高まる。いちいちprintf()を書かなくてよいし、デバッグ版からリリース版に移行するとき、デバッグ用のコードを消さなくてもよいのが利点である。まずはソースコードに assert.h をインクルードする。

assert() の使い方

#include <stdio.h>
#include <stdlib.h>

// まずは assert.h をインクルードする
// デバッグ版にはこれをアンコメントし、リリース版にはコメントをする
// #define  NDEBUG
#include <assert.h>

int main(void)
{
	int i = 1;
	
	// i は 0 なはずだ。
	assert(i == 0);

	exit(EXIT_SUCCESS);
}

このプログラムはassert(i == 0)のところで間違っているので、このソースコードコンパイルして実行するとこの部分が引っかかる。

リリース版ではNDEBUGを定義してからassert.hである。順番を間違えないこと。順番を間違えてしまえば、リリース版でもアサーションが効いてしまう。気をつけること。デバッグ版ではNDEBUGを定義してはならない。

さて、上のソースコードを実行すると次のメッセージが標準エラー出力に現れる。

Assertion failed: i == 0, file assert.c, line 12

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
上のエラーメッセージの和訳

アサーション失敗:i==0, file, assert.c, line 12

このアプリケーションはおかしな方向へのランタイム(実行時)に達してしまいました。
さらなる情報のためにアプリケーションのサポートチームにコンタクトしてください。

リリース版では関数(というかマクロ)の定義が無効になるので、メッセージも現れないし、assert()があることすらスキップされてコンパイルされる。

ちなみにこのメッセージでGoogleにかけると、リリース版なのにもかかわらずこのメッセージが出まくっていているアプリケーションがあるようなのだが、それはおそらくこの関数の使い方が分かっていないからなのだろう。

google:This application has requested the Runtime to terminate it in an unusual way.

あと、これ「ランタイムエラーです」っていうエラーメッセージを吐くけど、ライブラリのエラーじゃなくて実行時エラーのことだから、よく使われる意味でいわゆるモジュールの意味でのほうではないので、Googleで調べていてそこのところを勘違いした人がけっこういた。