4

我对一些代码运行 cppcheck 以查找可能的运行时错误。它报告了一个可能的空指针取消引用,情况如下:

Foo* x = ... //defined somewhere

...

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

编辑:更好的例子

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

来自 cppcheck 的错误消息:

[C:\file.cpp:3]:(错误)可能的空指针取消引用:x - 否则在第 4 行检查 x 是否为空是多余的

但我不明白这是怎么可能的。

4

3 回答 3

3

我真的很惊讶你收到了这个警告。对我来说,它的作用正好相反。使用从 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;

这最终会产生“可能的”空指针取消引用。可能的,对:

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

有趣的是,这虽然完全等同于前面的示例,但给出了明确的(不是“可能的”)空指针取消引用:

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

结论:cppcheck 是一个非常有问题的工具。

于 2010-12-18T11:29:45.807 回答
1

采取以下措施:

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

但是如果ptr_foo被写入程序的另一个点,另一个文件怎么办?例如,假设在someotherfile.c你找到:

ptr_null = 0;

那么,如果取消引用,则完全有可能在调用Foo* x = ptr_foo;时导致错误的 mojo 。y(x)yx

根据我的经验,静态分析工具往往会报告大量误报,因为它们没有关于程序的任何状态信息。

如果您真的想确保不会遇到空指针引用,您可以尝试以下操作:

Foo* x = 0;
if(ptr_foo != 0){
    x = ptr_foo;
}else{
    x = //something else
}
于 2010-12-17T20:14:39.053 回答
0

总结一下 Sergey Tachenov 的帖子:

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

现在 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.

下一个示例也被正确检测到:

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
于 2015-06-19T06:58:13.903 回答