公司要搞类似工具,所以调研了一下,我负责调研基于正则匹配的工具,我选择了cppcheck。 cppcheck支持的功能:
基本流程图:
PS: 符号化和simplify是对代码的两种处理,将代码简化为一个个token符号。
看了部分源码。 cli文件夹下面是入口函数和命令行支持的东西。
sample里面是一些bad代码例子,可以用工具测试一下。
lib里面有很多的checkXXX子类,是完成不同功能的,它们都要继承check父类,由check父类的构造函数完成instance挂载,并实现runchecks或者runsimplifychecks来做业务逻辑。
我们来看看看checkOther子类中对重复free错误的检查函数,,以此体会cppcheck的正则匹配检查方法。我在源代码里加了一点中文注释来说明:
void CheckOther::checkDoubleFree(){> freedVariables;> closeDirVariables;// 获取符号数据库const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();::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];// 遍历这个函数中的所有 tokenfor (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {(Token::Match(tok, “free|g_free|closedir ( %var% )”)) {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));elsecloseDirVariables.insert(varId);}}}(Token::Match(tok, “delete %var% ;”) || Token::Match(tok, “delete [ ] %var% ;”)) {const int varIndex = (tok->strAt(1) == “[“) ? 3 : 1;varId = tok->tokAt(varIndex)->varId();if (varId) {if (freedVariables.find(varId) != freedVariables.end())doubleFreeError(tok, tok->strAt(varIndex));elsefreedVariables.insert(varId);}}
基本情况就了解到这里。
世上最累人的事,莫过於虚伪的过日子