公司要搞类似工具,所以调研了一下,我负责调研基于正则匹配的工具,我选择了cppcheck。
cppcheck支持的功能:
基本流程图:
PS: 符号化和simplify是对代码的两种处理,将代码简化为一个个token符号。
看了部分源码。
cli文件夹下面是入口函数和命令行支持的东西。
sample里面是一些bad代码例子,可以用工具测试一下。
lib里面有很多的checkXXX子类,是完成不同功能的,它们都要继承check父类,由check父类的构造函数完成instance挂载,并实现runchecks或者runsimplifychecks来做业务逻辑。
我们来看看看checkOther子类中对重复free错误的检查函数,以此体会cppcheck的正则匹配检查方法。我在源代码里加了一点中文注释来说明:
void CheckOther::checkDoubleFree()
{
// 已经被free的变量
std::set<unsigned int> freedVariables;
// 已经被关闭的文件夹
std::set<unsigned int> closeDirVariables;
// 获取符号数据库
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
// 数据库中获取所有函数
const std::size_t functions = symbolDatabase->functionScopes.size();
// 遍历函数
for (std::size_t i = 0; i < functions; ++i) {
// 清空数据集
freedVariables.clear();
closeDirVariables.clear();
const Scope * scope = symbolDatabase->functionScopes[i];
// 遍历这个函数中的所有 token
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
// and report an error if the same variable is passed twice.
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
// (位移是1,所有2指的就是那个var变量
const unsigned int varId = tok->tokAt(2)->varId();
if (varId) {
// 正则匹配判断是否是 free 变量
if (Token::Match(tok, "free|g_free")) {
// 数据集里面有了? 说明是重复 free,报错
if (freedVariables.find(varId) != freedVariables.end())
doubleFreeError(tok, tok->strAt(2));
else
// 第一次? 加入数据集合吧
freedVariables.insert(varId);
// 不然就是文件夹
} else if (tok->str() == "closedir") {
// 一样判断是否重复
if (closeDirVariables.find(varId) != closeDirVariables.end())
doubleCloseDirError(tok, tok->strAt(2));
else
closeDirVariables.insert(varId);
}
}
}
// delete单独拿出来一样的逻辑用正则匹配来match
// Keep track of any variables operated on by "delete" or "delete[]"
// and report an error if the same variable is delete‘d twice.
else if (Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")) {
const int varIndex = (tok->strAt(1) == "[") ? 3 : 1;
const unsigned int varId = tok->tokAt(varIndex)->varId();
if (varId) {
if (freedVariables.find(varId) != freedVariables.end())
doubleFreeError(tok, tok->strAt(varIndex));
else
freedVariables.insert(varId);
}
}
基本情况就了解到这里。
原文:http://blog.csdn.net/linux4fun/article/details/44654983