2017-08-28 6 views
0

プロジェクト用にPVS-Studioを使用しますTorrent File Editor。偽陽性が1つあります。 Here本当の問題ではなく、私はこのようなエラーが出る:偽陽性V595 nullptrとの比較が確認される前に '_parent'ポインタが利用されました

torrent-file-editor/abstracttreenode.h:138: error: V595 The '_parent' pointer was utilized before it was verified against nullptr. Check lines: 138, 139.

コードスニペット:

inline T *sibling(int row) const 
{ 
    Q_ASSERT(_parent); 
    Q_ASSERT(row < _parent->childCount()); // -V595 PVS-Studio 
    return _parent ? _parent->child(row) : nullptr; 
} 

ここQ_ASSERTはデバッグバージョンチェックです。このようなチェックは、リリース版では実行されません。リリースでは、可能性のあるクラッシュを防ぐために_parent ? ... : ...を使用します。だから、デバッグバージョンで重複していることを確認しても問題ありません。

私はこの偽陽性を特別なコメントで抑えます。これは問題ではありませんが、PVS-Studioはこのケースを処理する必要があると考えています。

+0

assert()で動作しますか? LLVMのスタティックアナライザもQ_ASSERTと混同しているのを覚えています。 –

+0

assert()と同じです。 –

+0

次の場合: 'return _parent!= nullptr? _parent-> child(row):nullptr; '? – AlexanderVX

答えて

1

診断ロジックは単純です。最初にポインタが参照解除された場合、nullptrと等しいかどうかが検証された場合に警告が発行されます。

もちろん、このようなパターンに合致したアナライザが静かになる状況は数多くあります。ポインターがnullptrと等しくない状況を含めると、アナライザーは静かになります。

ただし、Q_ASSERT(_parent)は、ポインタ_parentがゼロでないことを保証しません。 _parentがゼロの場合、Q_ASSERTステートメントはqFatal関数を使用して次のメッセージを出力します。デフォルトのメッセージハンドラを使用している場合、この関数は中断してコアダンプを作成します。

独自のハンドラをインストールすることができます。ハンドラは、引き続きプログラムを実行します。理論的にはアナライザーは正しいです。 NULLポインタの潜在的な逆参照が発生する可能性があります。

私たちは理論家ではありませんが、実践的であり、このコードは正しいものとみなすべきです。このアナライザーは、マクロがまだ使用されているようなコードビューに精通していません。アナライザーを修正して、そのようなコードパターンを正しいものとして認識し始めます。私。ポインタ_parentはnullptrと等しい場合

Q_ASSERT(_parent); 
Q_ASSERT(row < _parent->childCount()); 

_parent->childCount()関数呼び出し、実行されることはありません:。将来アナライザで、ここでは、と仮定しますポインタがNULLの場合、プログラムはqFatal()を呼び出すため、以前の動作を停止します。

もちろん、上記のとおり、ハンドラの動作を変更することができ、プログラムを中止することはありません。しかし、実際には、誰もハンドラを変更し、ここで検討しているコードを書くことはありません。

これは答えの終点になる可能性があります。そこで、アナライザーを改良してみましょう。しかし、可能なすべてのオプションを予見することは不可能です。それが私たち自身のマクロならば、警告を抑制する方法は?

この自己生成エラーロギングシステムとアナライザーは、カスタム機能Foo()について何も知らないとしましょう。

Q_ASSERT(row < _parent->childCount()) //-V595 

別のオプションは、次のようにコードを書くのスタイルを変更して作成することです:

void Foo(bool expr); 
#define Q_ASSERT(expr) Foo(expr); 

inline T *sibling(int row) const 
{ 
    Q_ASSERT(_parent); 
    Q_ASSERT(row < _parent->childCount()) 
    return _parent ? _parent->child(row) : nullptr; 
} 

最も簡単ではなく、最良の方法は、明示的なコメントを使用している偽の警告マークにある

inline T *sibling(int row) const 
{ 
    if (_parent == nullptr) 
    { 
    Q_ASSERT(false); 
    return nullptr; 
    } 
    Q_ASSERT(row < _parent->childCount()); 
    return _parent->child(row); 
} 

このようなコードでは、理由がないため、アナライザは警告V595を発行しません。コードはもう少し長くなりましたが、私の意見では、これは論理的にはより正確で安全です。このような警告を扱うこの方法をお勧めします。

最後に、マクロで警告抑制メカニズムを使用します。この警告が表示されなくなります後

//-V:Q_ASSERT:595 

:マクロが定義されているヘッダファイルでこれを行うには、コメントを記述する必要があります。もちろん、マクロが宣言されているファイルを変更することは必ずしも可能ではありません。次に、グローバルファイルのいずれかを使用できます。 Visual C++プロジェクトでは、stdafx.hが適しています。もう1つのオプションは、診断設定ファイル(pvsconfig)を使用することです。これらの方法はすべて、ドキュメント「Suppression of false alarms」に詳しく記載されています。 markup baseも存在します。

関連する問題