c++可能的空指针取消引用

发布于 2024-10-08 19:11:00 字数 552 浏览 15 评论 0原文

我对一些代码运行了 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]:(错误)可能为 null 指针取消引用:x - 否则它 检查 x 是否为空是多余的 第 4 行

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

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 it
is redundant to check if x is null at
line 4

But I don't see how this is possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小忆控 2024-10-15 19:11:00

我真的很惊讶你收到这个警告。对我来说,效果恰恰相反。使用从 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;
  }
}

现在,使用 this 循环体,根据 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 是一个非常有缺陷的工具。

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.

清醇 2024-10-15 19:11:00

考虑以下情况:

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

但是如果 ptr_foo 被写入程序中的另一个点、另一个文件中怎么办?例如,假设在 someotherfile.c 中,您发现:

ptr_null = 0;

那么当 y(如果 y 取消引用 x,则调用 x)

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

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

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

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
}
最近可好 2024-10-15 19:11:00

对 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文