本当にassertを使うの?

3079 ワード

このブログを書くのはlighttpdソースコードを読むことでassertアプリケーションに関する疑問に直面したからです.
Lighttpdのソースコードを読むと、mallocの呼び出し結果をassertチェックします.例えば、Buffer.c:
buffer* buffer_init(void) {
buffer *b;

b = malloc(sizeof(*b));
assert(b);

b->ptr = NULL;
b->size = 0;
b->used = 0;

return b;
}

ここのassert(b)に問題があるようですが、実際にreleaseバージョンが実行中にmallocがNULLを返すことはありませんか?その後、《Writing Solid Code 》の本を読んで答えを見つけた.
assertの基本的な使い方はもう疲れませんが、assertの実際の応用であるRecommended practiceをまとめてみましょう.
1、断言で関数パラメータを確認する
主に次のような状況があります.
  • ポインタはNULLの断言ではありません.
  • index値またはsize値が負または既知の限界値未満の断言ではない.この1つは、プログラムから無定義の特性を削除するか、プログラムで断言を使用して無定義の特性の不正使用を検出する
  • についても説明することができる.
     
    2、各アサーションは、ヘッダファイルの関数機能記述のアサーション部分で説明しなければならない(他人の時間を無駄にしないでください.-詳細な説明がはっきりしないアサーション).例えば、次のようにします.
    *  Asserts:
    * 'size' is no greater then LIMIT.
    * 'format' is not NULL.
    * The function result is no greater than LIMIT.
    */

    断言がなければ「Nothing」と書きます.
     *  Asserts:
    * Nothing
    */
    ( , , )

    3、断言とエラーチェックの違い
    断言を正しく使用するには、プログラムエラー(program errors)とランタイムエラー(run-time errors)の違いを明確にしなければならない. 
  • プログラムエラーはバグであり、永遠に発生するべきではありません.
  • 実行時エラーは、プログラムの実行時に発生する可能性がある.

  • 断言はランタイムエラーを処理するメカニズムではありません.例えば正の数を入力する必要がある場合,ユーザは負の数を入力し,断言で検出すればよい設計ではない.この場合,適切なエラーチェックとリカバリ処理のコードで処理する必要がある.
    ライトtpdに戻ってmalloc関数の戻り値をassertで断言するのも、プログラムエラーではなく実行時エラーだと思います.だから、『Cとポインタ』という本ではmallocに対してNULLを返す処理は、エラーチェックディスペンサで処理されていると思います.
    4、断言とバグ
    断言は大きく分けて前置条件(Preconditions)、後置条件(Postconditions)、不変性条件(Invariants)
    前置条件が成立せず、Assertion violationsが発生した場合、この関数を呼び出すコードにバグが存在し、できるだけ早く見つけて解決する必要がある.
    後置条件が成立せず、Assertion violationsが発生した場合、(関数の)実装コードにバグがあり、できるだけ早く見つけて解決する必要がある.
    例:
    void doBlah(int x)

    {

    assert(x!=0);

    ....

    }

    このコードは、この関数の呼び出しがパラメータ0に入ることが不可能であることを示し、この場合、この関数を呼び出すコードにバグがあることを示す.
    以上は自分の少しの理解で、达人の指摘を歓迎します!!!参照:How to use assertions in C
            《 Writing Solid Code