assertマクロの使い方と原理


assertマクロのプロトタイプ定義はでは、その条件がエラーを返すとプログラム実行を終了し、プロトタイプ定義:#include void assert( int expression ); assertの役割は現在の計算式expressionであり、値が偽(0)の場合、stderrにエラーメッセージを印刷し、abortを呼び出してプログラムの実行を終了します.次のプログラムリストbadptr.c:#include#include#includeint main(void){FILE*fp;fp=fopen("test.txt","w")を参照してください.;//ファイルを書き込み可能に開き、存在しない場合は同じ名前のファイルassert(fp)を作成します.//だからここでfclose(fp);            fp = fopen( "noexitfile.txt", "r");//読み取り専用でファイルを開き、存在しない場合はファイルを開くのに失敗したassert(fp).//だからここでfclose(fp);//プログラムは永遠にここまで実行できませんreturn 0;}[root@localhost error_process]# gcc badptr.c  [root@localhost error_process]# ./a.out  a.out: badptr.c:14: main: Assertion `fp’’ failed. assertの使用を放棄した欠点は、頻繁な呼び出しがプログラムのパフォーマンスに大きく影響し、追加のオーバーヘッドを増加させることです.デバッグ終了後、#includeの文の前に#define NDEBUGを挿入するassert呼び出しを無効にする(ReleaseバージョンではNDEBUGというマクロ定数が定義されているため、Releaseバージョンではassertが無効である)、サンプルコードは以下の通りである:#include #define NDEBUG #include 用法総括と注意事項:1)関数の開始時に伝達パラメータの正当性を検証する(これは非常に重要であり、伝達された実パラメータが合法であるかどうかをタイムリーに検査し、合法でない場合は早めにプログラムの実行を終了する)例えば:int resetBufferSize(int nNewSize){//機能:バッファサイズ変更、//パラメータ:nNewSizeバッファ新長//戻り値:バッファ現在長//説明:元の情報内容をそのままにしておくnNewSize<=0はクリアバッファassert(nNewSize>=0)、assert(nNewSize<=MAX_BUFFER_SIZE)、…2)assertごとに1つの条件しか検証しない.複数の条件を同時に検証する場合、断言に失敗した場合、どの条件が失敗したのかを直感的に判断できない.assert(nOffset>=0&&nOffset+nSize<=m_nInfomationSize);はい:assert(nOffset>=0);assert(nOffset+nSize <= m_nInfomationSize);
3)環境を変更する文は使用できません.assertはDEBUG個でのみ有効であるため、このようにすると、プログラムが実際に実行されている間に問題が発生します.assert(i++<100)これは、エラー、例えば実行前にi=100であれば、この文は実行されないため、i++というコマンドは実行されません.正しい:assert(i<100)i++;4)assertと後の文は1行空けて、論理と視覚の一致感を形成しなければならない.
5)条件フィルタリングの代わりにassertができない箇所がある
 
 
 
Cでは、assertという断言が最も頻繁に使われているマクロの一つだと信じています.特にバグを探しているときは、間違いのコードに近づくことができると断言しています.多くは言わないで、私たちのテーマに入って、assertマクロを書きます.
まず、assertはdebug版で有効であり、release版ではassertが無効であることを知っています.では、この機能をどのように実現すればいいのでしょうか.実際releaseのバージョンではNDBUGというマクロ定数が定義されていますが、もちろんdebugでは定義されていませんので、このマクロを定義する前にNDBUGというマクロが定義されているかどうかをチェックすると、debug版かrelease版かがわかります.次のコードを参照してください.
 

  1 #if !defined(NDBUG)
2  #define assert(p) /* */
3  #else
4 #define assert(p)
5 #endif

 
今私たちが実現し続けているassertでは、もし失敗したら、失敗した場所のファイルのファイル名と行番号を出力すると断言していることを知っています.もちろん、出力は標準エラーにリダイレクトする必要があります.
 
__FILE__現在実行されているファイル名が記録されます.
__LINE__現在実行されている行番号を記録します.
stderrは標準エラーです.
もちろん失敗するとabortを呼び出してプログラムの実行を終了し,コードは以下のように実現すると断言する.
 

  1 #if !defined(NDBUG)
2 #define assert(p) if(!(p)){fprintf(stderr,/
3 "Assertion failed: %s, file %s, line %d/n",/
4 #p, __FILE__, __LINE__);abort();}
5 #else
6 #define assert(p)
7 #endif