clang静态分析仪跳过一些检查

时间:2018-02-09 11:19:01

标签: c++ frontend llvm-clang clang-static-analyzer

我正在使用clang静态分析器4.0.0。 对于以下示例

int fun(){

    int aa = 1,bb = 0;
    int cc = aa/bb; // 1) devide by zero. // Reported by clang

    int *pt = nullptr;
    int a = *pt;    // 2) null pointer dereference. // NOT Reported by clang

    int b;
    int c = a + b;  // 3) Unused initialization. // Reported by clang

    return cc;
}

Clang静态分析器仅报告两个问题1和3,并跳过问题2.

然而,如果我改变了这样的问题顺序

int fun(){

    int *pt = nullptr;
    int a = *pt;    // 1) null pointer dereference. // Reported by clang

    int aa = 1,bb = 0;
    int cc = aa/bb; // 2) devide by zero. // NOT Reported by clang

    int b;
    int c = a + b;  // 3) Unused initialization. // Reported by clang

    return cc;
}

然后clang静态分析器报告1和3并跳过2。

我正在使用此命令运行clang静态分析器

  

clang-check.exe -analyze D:\ testsrc \ anothercpp.cpp

这是非常不一致的行为。无论问题的顺序如何,其中一个问题都会被忽略。 另外,我使用clang 5.0.1检查了这个场景,但结果却相同。

有人知道为什么静态分析仪会发生这种情况吗?

提前致谢。

-Hemant

2 个答案:

答案 0 :(得分:4)

快速查看代码,您观察到的行为似乎是设计的。

当可能发现空指针取消引用的DereferenceChecker报告错误时,它会创建一个“错误节点”,阻止进一步探索路径敏感的分析。

void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
                                   CheckerContext &C) const {
  // Generate an error node.
ExplodedNode *N = C.generateErrorNode(State);

CheckerContext :: generateErrorNode为documented,用于停止通过程序探索给定路径。

  /// \brief Generate a transition to a node that will be used to report
  /// an error. This node will be a sink. That is, it will stop exploration of
  /// the given path.
  ///
  /// @param State The state of the generated node.
  /// @param Tag The tag to uniquely identify the creation site. If null,
  ///        the default tag for the checker will be used.
  ExplodedNode *generateErrorNode(ProgramStateRef State = nullptr,
                                  const ProgramPointTag *Tag = nullptr) {
    return generateSink(State, Pred,
                       (Tag ? Tag : Location.getTag()));
}

这是有道理的,因为在作为空指针解除引用的严重错误之后,对于程序没有多少有意义的预测。由于C ++中的空指针解除引用是undefined behaviour,因此该标准允许任何事情发生。只有通过查看程序的详细信息及其运行的环境,才能做出更多预测。可能这些预测超出了静态分析仪的范围。

实际上,您一次只能修复一个错误,并且可能会继续修复错误,直到静态分析器停止发出有效投诉为止。

检测未使用的变量不需要路径敏感分析。因此,这种类型的检查器仍然有效。

答案 1 :(得分:1)

所有这些都表明您无法为静态分析器编写一些原始的人工测试。我在文章" Why I Dislike Synthetic Tests"中详细讨论过这个问题。它最有可能出于某些内部原因(但肯定不是因为错误),Clang分析器会跳过空取消引用操作之后的代码片段,这显然会导致未定义的行为。或者它可能因为除零而跳过。这没什么不对的。在空取消引用或除以零之后写入的内容实际上并不重要:后续代码无论如何都不会执行。所以,这个问题与编译器/分析器的错误无关,而是像这样粗心编写的测试的结果。为诊断编写一个好的测试是一项艰巨的工作,这需要您小心并了解许多细微的细节。