ASSERT(pointer);
pointer->x;
このコードでは、ASSERT が冗長に見えます。ポインタが NULL の場合、pointer->x はとにかく失敗します。私の主張は正しいですか?
アサーションの (主要ではないにしても) 重要な目的は、コード内の特定のポイントで保持されるはずの不変条件を文書化することです。不変条件が壊れている場合にプログラムを中止することもできるという事実assert
は、非常に便利なものではありますが、ケーキのアイシングです。典型的なプログラムでは、アサーションの 90% は、明らかに失敗することがなく、決して失敗しないアサーションであると言えます。言い換えれば、assert
はかなりの程度、一種の形式化されたコメント言語です。これらの「コメント」は、平易な英語ではなく、残りのコードが (C/C++) で書かれているのと同じ言語で書かれているという意味で形式化されています。
あなたのコードサンプルでは、ポインターがここで null であってはならないことを示すアサーションがあります。それがそこにある理由です。その意味で、これassert
は冗長ではありません。
実行フローに関する限り、assert
は常に冗長です。そのため、アサーションは通常、リリース バージョンのコードではコンパイルされません。リリースコードにもアサーションを保持することを妨げるものは何もありませんが、通常は特別な種類の「リリースアサーション」を導入することによって行われます。いずれにせよ、コードの主な機能をアサーションによって実行されるアクションに依存させることは、適切なプログラミング手法ではありません。コードの主な機能に関する限り、アサーションは冗長であると想定されています。
はい、しかしpointer->x
(私が推測するに) 制御されていない方法で失敗しますが、assert
は失敗し、正確な場所を教えてくれます。
もちろん、ある意味でassert
は常に冗長です。
いいえ、冗長ではありません。アサーションは、悪いことが起こる前に実行を停止します。一方、無効なポインターを逆参照すると、実際の破損が発生するか、少なくとも制御された中止ではなく、制御されていないセグメンテーション違反が発生する可能性があります。
ASSERT
C標準の一部ではないため、何でもかまいません
#define ASSERT(x) do { \
x = malloc ( sizeof *x ); \
memset ( x, 0, sizeof *x );\
} while ( 0 )
assert
は別問題です。
デバッガーを呼び出すマクロを持っている人もいれば、ASSERT
他のデバッグやロギングを行うマクロを持っている人もいれば、プリプロセッサーの文字列化機能を使用する人もいます。
マクロが重要かどうかを知るには、マクロが何をするかを実際に説明する必要があります。
場合によっては、アサートをデバッグに使用できます http://simonwillison.net/2008/May/22/debugging/
ASSERT
また、クラッシュを引き起こさない可能性のある無効または非論理的な条件をチェックするためにも使用できます。これは恐ろしく不自然な例です:
void cpu_hog(int duration)
{
int start_time = (int) time(NULL);
int end_time = start_time + duration;
ASSERT(end_time > start_time); /* If this fails, "int" is too small. */
while ((int) time(NULL) < end_time)
;
}
1 つの小さな注意: ほとんどの支持者はASSERT
、コードを記述するときに行う仮定を検証するためだけに使用することをお勧めします (たとえば、ポインターが非 NULL である、または条件が発生しないなど)。一般に、(1)デバッグ ビルドにのみ存在し、(2) デバッグ コードをプロモートした場合でも、発生が予想されるユーザー関連のエラーまたは例外 (ディスクがいっぱいなど) をトラップするために使用することはお勧めできません。本番環境に移行すると、条件を適切に処理する代わりにクラッシュします。ASSERT
ASSERT
ASSERT は失敗しません。ブレークポイントでデバッガーを停止するためにここにあります。これはリリース ビルドには影響しません。