我正在使用 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 检查了这种情况,结果相同。
有人知道为什么静态分析器会发生这种情况吗?
提前致谢。
-赫曼特
最佳答案
快速查看代码,您观察到的行为似乎是设计使然。
当 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()));
}
这是有道理的,因为在出现像空指针取消引用这样严重的错误之后,无法对程序做出很多有意义的预测。由于空指针取消引用是 undefined behaviour在 C++ 中,标准允许任何事情发生。只有查看程序的细节及其运行的环境,才能做出更多的预测。这些预测可能超出静态分析器的范围。
在实践中,您一次只能修复一个错误,并且可能会继续修复错误,直到静态分析器停止提出有效的投诉。
检测未使用的变量不需要路径敏感分析。因此,这种类型的检查器仍然有效。
关于c++ - clang 静态分析器跳过一些检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48704681/