私はOpenCVのチュートリアルを勉強していてassert
関数に出会いました。それは何をするためのものか?
assert
は、引数がfalseであることが判明した場合、プログラムを終了させます(通常はassert文を引用するメッセージで)。予期しない状態が発生した場合にプログラムをより明確に失敗させるためにデバッグ中によく使用されます。
例えば:
assert(length >= 0); // die if length is negative.
失敗した場合に表示されるより有益なメッセージを追加することもできます。
assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
それとも他にもこんな感じ:
assert(("Length can't possibly be negative! Tell jsmith", length >= 0));
リリース(非デバッグ)ビルドを行っているときは、assert
マクロを定義することで(通常はコンパイラー・スイッチを使用して)、NDEBUG
ステートメントを評価することによるオーバーヘッドを除去することもできます。この結果として、あなたのプログラムは決して assertマクロの実行に頼るべきではないということです。
// BAD
assert(x++);
// GOOD
assert(x);
x++;
// Watch out! Depends on the function:
assert(foo());
// Here's a safer way:
int ret = foo();
assert(ret);
Abort()を呼び出すプログラムと何もしないことが保証されていないことの組み合わせから、たとえばユーザーが文字ではなく数字を入力するのではなく、開発者が仮定したことをテストするためだけにassertを使用します。他の手段によって処理されます。
assert computerステートメントは、英語のsureステートメントに似ています。
を見てみましょう
多くのコンパイラはassert()マクロを提供しています。 assert()マクロは、パラメータがTRUEと評価された場合はTRUEを返し、FALSEと評価された場合は何らかの種類のアクションを実行します。多くのコンパイラは、失敗したassert()でプログラムを中止します。他の人は例外をスローします
Assert()マクロの強力な機能の1つは、DEBUGが定義されていない場合にプリプロセッサがコードをまったくコードなしに折りたたむことです。開発中、そして最終製品が出荷されたときには、パフォーマンスの低下やプログラムの実行可能バージョンのサイズの増加はありません。
例えば
#include <stdio.h>
#include <assert.h>
void analyze (char *, int);
int main(void)
{
char *string = "ABC";
int length = 3;
analyze(string, length);
printf("The string %s is not null or empty, "
"and has length %d \n", string, length);
}
void analyze(char *string, int length)
{
assert(string != NULL); /* cannot be NULL */
assert(*string != '\0'); /* cannot be empty */
assert(length > 0); /* must be positive */
}
/**************** Output should be similar to ******************
The string ABC is not null or empty, and has length 3
Assert()関数はプログラムのバグを診断できます。これは<assert.h>
で定義されており、そのプロトタイプは
void assert(int expression);
引数式はテストしたいものなら何でもかまいません - 変数かCの式です。 expressionがTRUEと評価された場合、assert()は何もしません。 expressionがFALSEと評価された場合、assert()は標準エラー出力にエラーメッセージを表示してプログラムの実行を中止します。
どのようにassert()を使用しますか?プログラムのバグを追跡するために最もよく使用されます(コンパイルエラーとは異なります)。バグによってプログラムのコンパイルが妨げられることはありませんが、誤った結果が出たり、不適切に実行されたりすることがあります(たとえば、ハングアップ)。例えば、あなたが書いている財務分析プログラムは時々間違った答えを与えるかもしれません。あなたは、この問題が変数interest_rateが負の値をとることによって引き起こされているのではないかと考えています。これを確認するには、次の文を配置します。
assert(interest_rate> = 0); interest_rateが使用されているプログラム内の場所。変数が負になると、assert()マクロが警告します。その後、関連するコードを調べて問題の原因を突き止めることができます。
assert()がどのように機能するかを見るためには、以下のサンプルプログラムを実行してください。ゼロ以外の値を入力すると、プログラムはその値を表示して正常に終了します。ゼロを入力すると、assert()マクロはプログラムの異常終了を強制します。表示される正確なエラーメッセージはコンパイラによって異なりますが、これは典型的な例です。
アサーションが失敗しました:x、ファイルlist19_3.c、行13注:assert()が機能するためには、プログラムをデバッグモードでコンパイルする必要があります。デバッグモードを有効にする方法については、コンパイラのマニュアルを参照してください(後で説明します)。後で最終バージョンをリリースモードでコンパイルすると、assert()マクロは無効になります。
int x;
printf("\nEnter an integer value: ");
scanf("%d", &x);
assert(x >= 0);
printf("You entered %d.\n", x);
return(0);
整数値を入力してください:10
10を入力しました。
整数値を入力してください:-1
エラーメッセージ:プログラムの異常終了
あなたのエラーメッセージはあなたのシステムやコンパイラによって異なるかもしれませんが、一般的な考え方は同じです。
「例外を発生させる」や「実行を停止する」のようなものはほとんどのコンパイラに当てはまるかもしれませんが、すべてには当てはまりません。 (ところで、本当に例外をスローするアサートステートメントはありますか?)
これは、c6xや他のTIコンパイラで使用されている興味深い、わずかに異なるassertの意味です。特定のassert文を見ると、これらのコンパイラは特定の最適化を実行するためにその文の情報を使用します。邪悪だ。
Cの例:
int dot_product(short *x, short *y, short z)
{
int sum = 0
int i;
assert( ( (int)(x) & 0x3 ) == 0 );
assert( ( (int)(y) & 0x3 ) == 0 );
for( i = 0 ; i < z ; ++i )
sum += x[ i ] * y[ i ];
return sum;
}
これは、配列が32ビット境界で整列されるようにコンパイラに指示するので、コンパイラはそのような整列のために作られた特定の命令を生成できます。
C++ 11 N3337標準ドラフト
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3アサーション
1(表42)に説明されているヘッダー<cassert>は、C++プログラムのアサーションを文書化するためのマクロと、アサーションチェックを無効にするためのメカニズムを提供します。
2内容は標準Cライブラリヘッダ<assert.h>と同じです。
C99 N1256標準ドラフト
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
7.2診断<assert.h>
1ヘッダー
<assert.h>
はassertマクロを定義し、<assert.h>
で定義されていない別のマクロNDEBUG
を参照します。 <assert.h>が含まれているソースファイル内の位置でNDEBUG
がマクロ名として定義されている場合、assertマクロは単純に次のように定義されます。#define assert(ignore) ((void)0)
<assert.h>
が含まれるたびに、assertマクロはNDEBUGの現在の状態に従って再定義されます。2. assertマクロは、実際の関数としてではなく、マクロとして実装されます。実際の関数にアクセスするためにマクロ定義が抑制されている場合の動作は未定義です。
7.2.1プログラム診断
7.2.1.1 assertマクロ
あらすじ
1。
#include <assert.h> void assert(scalar expression);
説明
2 assertマクロは診断テストをプログラムに入れます。それはvoid式に展開されます。実行時にexpression(スカラー型)がfalse(つまり、0と比較)の場合、assertマクロは失敗した特定の呼び出しに関する情報(引数のテキスト、名前など)を書き込みます。ソースファイル、ソース行番号、およびそれを囲む関数の名前。後者はそれぞれ、標準エラーストリーム上のプリプロセスマクロ
__FILE__
および__LINE__
、および識別子__func__
)の値です。 165)それから中止関数を呼び出します。返品
3 assertマクロは値を返しません。
アサートにより、条件(アサーション)が偽の場合に実行を停止することができます。
例えば(疑似コード):
Bank myBank = Bank.GetMyStuff();
assert(myBank != NULL);
// .. Continue.
MyBankがNULLの場合、関数は実行を停止し、エラーが発生します。これは、特定の再利用可能なコードに正しい条件などを受け入れさせるために非常に役立ちます。
評価した値がfalseの場合にプログラムの実行を停止する関数です。通常はマクロで囲まれているため、リリース設定でコンパイルしたときに結果のバイナリにコンパイルされません。
それはあなたがした仮定をテストするために使われるように設計されています。例えば:
void strcpy(char* dest, char* src){
//pointers shouldn't be null
assert(dest!=null);
assert(src!=null);
//copy string
while(*dest++ = *src++);
}
理想的なのは、無効な引数を使用して関数を呼び出すなど、プログラムでエラーを起こすことができ、セグメンテーション違反が発生する前にアサートをヒットした(または期待通りに動作しなかった)ことです。
Else ifおよびprintfの場合に比べて、assert()関数を通常よりも使用する主な理由が3つあります。
assert()関数は主にデバッグ段階で使われますが、最終コードではうまく行かないかもしれない条件をテストしたいときはいつもprintfステートメントで書くのは面倒です。
大規模なソフトウェア展開では、assert()関数のヘッダーファイルをリンクする前に定義されたNDEBUGマクロを使用してコンパイラにassertステートメントを無視させることができる場合、assertは非常に便利です。
関数(またはコード)を設計していて、そのコードが何を制限し、機能しないかについてアイデアを得たい場合、assert()が便利です。