静态代码检查工具cppcheck初探

公司要搞类似工具,所以调研了一下,我负责调研基于正则匹配的工具,我选择了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);
                }
            }

基本情况就了解到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值