开发者

c++ Possible null pointer dereference

开发者 https://www.devze.com 2023-01-31 08:10 出处:网络
I ran cppcheck over some code to look for possible runtime errors. And it is reporting a possible null pointer dereference with the following situation:

I ran cppcheck over some code to look for possible runtime errors. And it is reporting a possible null pointer dereference with the following situation:

Foo* x = ... //defined somewhere

...

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

Edit: Better example

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

Error message from cppcheck:

[C:\file.cpp:3]: (error) Possible null pointer dereference: x - otherwise i开发者_如何学Ct is redundant to check if x is null at line 4

But I don't see how this is possible.


I am really surprised that you got that warning. For me, it works exactly the opposite. Using cppcheck 1.46.1 compiled from sources in Linux. This is fine:

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;
  }
}

Now, with this loop body it is also "fine" according to cppcheck although it segfaults if I actually try to run it, obviously:

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

Even this is "fine":

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

And this finally generates "possible" null pointer dereference. Possible, right:

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

The funny thing is that this, while being completely equivalent to an earlier example, gives definite (not "possible") null pointer dereference:

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

The conclusion: cppcheck is a really buggy tool.


Take the following:

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

But what if ptr_foo was written to at another point in the program, in another file? For example, let's say that in someotherfile.c you find:

ptr_null = 0;

Then it is entirely possible that Foo* x = ptr_foo; could cause bad mojo, when y(x) is called, if y dereferences x.

From my experience, static analysis tools tend to report a large number of false positives, because they do not have any state information about the program.

If you really want to make sure you won't run into a null pointer reference, you could try something like:

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


Just a wrap up to the post from Sergey Tachenov:

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

This one is now correctly detected by cppcheck:

 $ 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.

Also the next example is detected correctly:

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

Here is the output from cppcheck:

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

Even the next example demonstrates that Cppcheck works as expected:

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

Here is the output:

$ cppcheck --enable=all nullptrderef11.cpp
  Checking nullptrderef11.cpp...
  [nullptrderef11.cpp:18]: (error) Possible null pointer dereference: p
  [nullptrderef11.cpp:18]: (error) Null pointer dereference
0

精彩评论

暂无评论...
验证码 换一张
取 消