首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >假阳性V595‘nullptr’指针在针对nullptr进行验证之前已被使用

假阳性V595‘nullptr’指针在针对nullptr进行验证之前已被使用
EN

Stack Overflow用户
提问于 2017-08-28 17:02:01
回答 1查看 114关注 0票数 0

我将PVS-Studio用于我的项目Torrent File Editor。有一个假阳性。Here没有真正的问题,但我得到这样的错误:

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

代码片段:

代码语言:javascript
复制
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 ? ... : ...来防止可能的崩溃。所以在Debug版本中检查重复是完全正常的。

我用特别的评论来抑制这个假阳性。所以这不是问题,但我认为PVS-Studio应该处理这种情况。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-29 14:53:49

V595诊断逻辑很简单。如果在开始时指针被解除引用,然后验证是否与nullptr相等,则会发出警告。

当然,在遇到这样的模式后,分析器会在许多情况下保持安静。包括指针不等于nullptr的情况,因此分析器将保持安静。

但是,Q_ASSERT(_parent)不能保证指针_parent为非零。如果_parent为零,则Q_ASSERT语句将使用qFatal函数输出以下消息。如果您使用的是默认消息处理程序,则此函数将中止以创建核心转储。

您可以安装自己的处理程序,它将继续运行程序。所以从理论上讲分析器是正确的。可能会发生空指针的取消引用。

我们不是理论家,而是实践者,我们意识到这个准则应该被认为是正确的。分析器不熟悉这样的代码视图,其中还使用宏Q_ASSERT。我们将修改分析器,以便它开始感知这种代码模式是正确的。也就是说,在未来分析器将在这里假设:

代码语言:javascript
复制
Q_ASSERT(_parent);
Q_ASSERT(row < _parent->childCount());

如果指针_parent等于nullptr,则永远不会执行_parent->childCount()函数调用。如果指针为空,则程序将因为调用qFatal()而提前停止工作。

当然,正如我在上面已经说过的,您可以更改处理程序的行为,这不会导致程序中止。但是,在实践中,没有人会更改处理程序并编写我们在这里考虑的代码。

这可能是答案的终点。因此,我们将改进分析器,仅此而已。然而,不可能预见所有可能的选择。如何抑制警告,如果它是我们自己的宏?

让我们假设这个自制的错误记录系统和分析器对自定义函数Foo()一无所知。

代码语言:javascript
复制
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;
}

最简单但不是最好的方法是使用注释显式地将警告标记为false:

代码语言:javascript
复制
Q_ASSERT(row < _parent->childCount())   //-V595

另一种选择是更改代码的编写风格,并按如下方式编写:

代码语言:javascript
复制
inline T *sibling(int row) const
{
  if (_parent == nullptr)
  {
    Q_ASSERT(false);
    return nullptr;
  }
  Q_ASSERT(row < _parent->childCount());
  return _parent->child(row);
}

对于这样的代码,分析器不会发出警告V595,因为没有理由这样做。代码变得有点长了,但在我看来,它现在在逻辑上更正确,也更安全。我推荐用这种方式来处理这种类型的警告。

最后是在宏中使用警告抑制机制。要在定义宏的头文件中执行此操作,应编写注释:

代码语言:javascript
复制
//-V:Q_ASSERT:595

在此之后,警告将消失。当然,并非总是可以更改声明宏的文件。然后,您可以使用其中一个全局文件。在可视化C++项目中,stdafx.h是一个很好的候选者。另一种选择是使用诊断配置文件(pvsconfig)。所有这些方法都在"Suppression of false alarms“一节的文档中进行了详细描述。markup base也存在。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45915338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档