はので、ここで、悪い考えで、以下のテーマに関する私の詳細な応答である:
これは可能ですが、すべての に定義する含めるように痛みだろうテストケースファイル。また、これはBOOST_REQUIREに限定されず、 は、アサート、SDL_Assert、またはユーザー が使用するその他のカスタムマクロにも適用されます。
一つは、テスト・マクロの3種類があることを理解する必要があり、それぞれが個別に議論されるべきです。
最初のタイプのマクロは、デバッグバージョンで何か問題が発生したことを警告するだけです。典型的な例はassert
マクロです。次のコードは、警告を生成するために、PVS-Studioのアナライザを引き起こします:
T* p = dynamic_cast<T *>(x);
assert(p);
p->foo();
アナライザは、ここでは逆参照可能ヌル・ポインタを指摘すると、右になります。 assert
を使用するチェックは、リリースバージョンから削除されるため、十分ではありません。つまり、チェックがないことが分かります。実装するより良い方法は、コードを次のように書き換えることです。
T* p = dynamic_cast<T *>(x);
if (p == nullptr)
{
assert(false);
throw Error;
}
p->foo();
このコードは警告をトリガーしません。
あなたは、dynamic_cast
が決してnullptr
を返さないことを100%確信していると主張できます。私はこの議論を受け入れません。キャストが常に正しいことを完全に確信している場合は、より速くstatic_cast
を使用する必要があります。それが確実でない場合は、逆参照する前にポインタをテストする必要があります。
さて、わかりました、あなたの意見があります。コードは問題ないと確信していますが、場合によってはdynamic_castでチェックする必要があります。 OK、その後、次のコードを使用します。
assert(dynamic_cast<T *>(x) != nullptr);
T* p = static_cast<T *>(x);
p->foo();
を私はそれが好きではありませんが、アナライザは黙ってする一方、より遅いdynamic_cast演算子は、リリースバージョンに取り残されるので、少なくともそれは、高速です。
次のタイプのマクロに移動します。
マクロは、デバッグバージョンで何か問題が発生し、テストで使用されていることを警告します。以前のタイプと異なる点は、条件が偽でエラーメッセージが生成された場合、テスト中のアルゴリズムを停止することです。
これらのマクロの基本的な問題は、関数が非復帰としてマークされていないことです。ここに例があります。
例外をスローしてエラーメッセージを生成する関数があるとします。
void Error(const char *message);
そして、これは、テストマクロが宣言されている方法です:
#define ENSURE(x) do { if (!x) Error("zzzz"); } while (0)
ポインタを使用する:
T* p = dynamic_cast<T *>(x);
ENSURE(p);
p->foo();
アナライザはに関する警告が発行されますこれは、その宣言は次のようになりますnullポインタの逆参照が可能ですが、コードは実際に安全です。ポインタがNULLの場合、Error
関数は例外をスローし、ポインタの逆参照を防止します。
私たちは、単に例えば、機能注釈手段のいずれかを使用して、そのことについて解析を伝える必要があります:
[[noreturn]] void Error(const char *message);
か:
__declspec(noreturn) void Error(const char *message);
これが偽の警告を排除するのに役立ちます。したがって、あなたが見ることができるように、あなた自身のマクロを使用している場合、ほとんどの場合、事を修正するのは非常に簡単です。
しかし、サードパーティ製のライブラリから不注意に実装されたマクロを処理するのは難しいかもしれません。
これは、3番目のタイプのマクロにつながります。それらを変更することはできず、アナライザは正確にどのように動作するか把握できません。これは、マクロが非常にエキゾチックな方法で実装される可能性があるため、一般的な状況です。
このケースでは、あなたのために残され、3つのオプションがあります:
- が偽陽性抑制のいずれかを使用して警告がdocumentationに記載の手段抑えます。
- は、前のanswerで説明した手法を使用します。
- メールでお問い合わせください。
一般的なライブラリからさまざまなトリッキーなマクロのサポートが徐々に追加されています。実際には、アナライザーは遭遇する可能性のあるマクロの大部分をすでによく知っていますが、プログラマーの想像力は無尽蔵であり、可能なすべての実装を予見できません。
返信いただきありがとうございます。これは可能ですが、その定義をすべてのテストケースファイルに含めることは苦労でしょう。また、これは 'BOOST_REQUIRE'だけに限定されず、' assert'や 'SDL_Assert'やその他のカスタムマクロにも適用されます。だから私は2つの解決策を見てみましょう:ユーザーが "assert" -macro名のリストを指定できるようにしてください。その後、条件がtrueであると仮定されます(それがアサートの理由です)。 – Flamefire
少なくとも、グローバルなPVS専用のファイルがあり、PVSによって読み込まれ、使用されることが想定されています( 'cpp.hint'に似ています)。したがって、そのような定義を中央の場所に置くことができます。しかし、私はこれが難しいと思います。なぜなら、定義はすべてのファイルに含まれるからです。 – Flamefire