2010-12-17 22 views
4

実行可能なエラーを探すために、いくつかのコードに対してcppcheckを実行しました。そして、それは次のような状況で可能なヌルポインタ参照を報告している:C++可能なnullポインタ逆参照

Foo* x = ... //defined somewhere 

... 

Foo* y(x); //possible null pointer dereference. 

編集:より良い例cppcheckから

for(int i = 0; i < N; i++) 
{ 
    Foo* x(ArrayOfObjsContainingFooPtr[i].FooPtr); // line 3 
    if(!x)           // line 4 
     continue; 
} 

エラーメッセージ:

[C:\ file.cpp :3]:(エラー)可能なヌル ポインタ参照:x - それ以外の場合 はxがヌルであることを確認するために冗長です 行4

しかし、これはどのように可能かわかりません。

+3

あなたはより完全な例を投稿することができますか?私はこの状況につながるコードパスがあると思う。静的コード分析ツールは完全ではないことに注意してください。これは誤ったポジティブなものかもしれません。 –

+0

更新された元の質問 – Glaeken

+0

これらの例のどちらもxを逆参照しません。 –

答えて

1

は、次のことを取る:

Foo* x = ptr_foo; //ptr_foo is defined earlier in the code. 

しかし、別のファイルでは、プログラム内の他の点ではどうptr_foo場合に書かれていましたか?たとえば、のはsomeotherfile.cであなたを見つけることを言わせて:

ptr_null = 0; 

そして、Foo* x = ptr_foo;yデリファレンスx場合y(x)が、呼び出された悪いモジョを引き起こす可能性があるということは完全に可能です。

私の経験から、静的解析ツールは、プログラムに関する状態情報がないため、多数の誤検出を報告する傾向があります。

Foo* x = 0; 
if(ptr_foo != 0){ 
    x = ptr_foo; 
}else{ 
    x = //something else 
} 
+0

コードサンプルの代替(IMHOクリーナー)バージョン: 'Foo * x = ptr_foo? ptr_foo:/ * something else * /; ' –

+0

いいえ、「Foo * x = ptr_foo;悪いmojoになる可能性はありません。これはポインタのコピーであり、逆参照ではありません。 –

+0

これは私が考えていたものです。 – Glaeken

3

私はあなたがその警告を得たことは本当に驚いて:あなたは本当にあなたはNULLポインタ参照に実行されませんを確認するには

、あなたのような何かを試みることができます。私のために、それはちょうど反対の作品です。 Linuxのソースからコンパイルされたcppcheck 1.46.1の使用。これは結構です:それもあるこのループ本体で今すぐ

struct Foo { 
    int x; 
}; 

struct Obj { 
    Foo *FooPtr; 
}; 

#define N 10 

static Obj ArrayOfObjsContainingFooPtr[N]; 

int main() { 
    for(int i = 0; i < N; i++) { 
    Foo* x(ArrayOfObjsContainingFooPtr[i].FooPtr); // line 3 
    if(!x)           // line 4 
     continue; 
    } 
} 

、私は実際にそれを実行しようとすると、「ファイン」はcppcheckによると、それは明らかに、セグメンテーション違反が:でもこの

Foo* x(ArrayOfObjsContainingFooPtr[i].FooPtr); // line 3 
if (x->x == 0) 
    break; 
if(!x)           // line 4 
    continue; 

これは最終的に "可能な"ヌルポインタ逆参照を生成します。可能性のある、右:

int main() { 
    Foo *p = 0; 
    if ((*p).x == 0) 
    return 1; 

結論:cppcheck

int main() { 
    Foo *p = 0; 
    p->x = 0; 

面白いことに、これは、以前の例と完全に同等でありながら、(「可能」ではない)明確なヌルポインタ参照を与えるということです本当にバギーなツールです。セルゲイTachenovからポストへ

+0

+1:このツールの多くの不具合を明らかにするために、この質問に非常に関連していて、明らかに見つけにくいものではありません。 – rubenvb

+0

遅くは言わない... –

0

ちょうどラップアップ:また、次の例が正しく検出され

$ cppcheck --enable=all nullptrderef9.cpp 
Checking nullptrderef9.cpp... 
[nullptrderef9.cpp:20] -> [nullptrderef9.cpp:22]: (warning) Possible null pointer dereference: x - otherwise it is redundant to check it against null. 

を::この1は正しくcppcheckによって検出された

Foo* x(ArrayOfObjsContainingFooPtr[i].FooPtr); // line 3 
if (x->x == 0) 
break; 
if(!x)           // line 4 
continue; 

int main() { 
    Foo *p = 0; 
    if (p->x == 0) 
    return 1; 
} 

ここにcppcheckの出力があります。

$ cppcheck --enable=all nullptrderef10.cpp 
Checking nullptrderef10.cpp... 
[nullptrderef10.cpp:19]: (error) Possible null pointer dereference: p 

であっても、次の例では、期待通りCppcheckが機能することを示しています

int main() 
{ 
    Foo *p = 0; 
    if ((*p).x == 0) 
     return 1; 
} 

ここで出力されます:

$ cppcheck --enable=all nullptrderef11.cpp 
    Checking nullptrderef11.cpp... 
    [nullptrderef11.cpp:18]: (error) Possible null pointer dereference: p 
    [nullptrderef11.cpp:18]: (error) Null pointer dereference 
関連する問題