⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 checkmemoryleak.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            {                alloc = GetReallocationType(tok->tokAt(2));                if (alloc != No)                {                    addtoken("realloc");                    addtoken(";");                    realloc = true;                }            }            // If "--all" hasn't been given, don't check classes..            if (alloc == New)            {                if (Token::Match(tok->tokAt(2), "new %type% [(;]"))                {                    if (isclass(tok->tokAt(3)))                    {                        if (_settings._showAll)                        {                            if (_settings.isAutoDealloc(tok->strAt(3)))                            {                                // This class has automatic deallocation                                alloc = No;                            }                            else                            {                                // The checking will proceed.. but any error messages that are shown are shown thanks to "--all"                                all = true;                            }                        }                        else                            alloc = No;                    }                }            }            if (alloc != No)            {                if (! realloc)                    addtoken("alloc");                if (alloctype != No && alloctype != alloc)                    alloc = Many;                if (alloc != Many && dealloctype != No && dealloctype != Many && dealloctype != alloc)                {                    callstack.push_back(tok);                    _errorLogger->mismatchAllocDealloc(_tokenizer, callstack, varname);                    callstack.pop_back();                }                alloctype = alloc;            }            else if (MatchFunctionsThatReturnArg(tok->previous(), std::string(varname)))            {                addtoken("use");            }            // assignment..            else            {                // is the pointer in rhs?                bool rhs = false;                std::string pattern("[=+] " + std::string(varname));                for (const Token *tok2 = tok; tok2; tok2 = tok2->next())                {                    if (tok2->str() == ";")                        break;                    if (Token::Match(tok2, pattern.c_str()))                    {                        rhs = true;                        break;                    }                }                addtoken((rhs ? "use" : "assign"));            }        }        if (Token::Match(tok->previous(), "[;{})] %var%"))        {            AllocType dealloc = GetDeallocationType(tok, varnames);            if (dealloc != No)            {                addtoken("dealloc");                if (dealloctype != No && dealloctype != dealloc)                    dealloc = Many;                if (dealloc != Many && alloctype != No && alloctype != Many && alloctype != dealloc)                {                    callstack.push_back(tok);                    _errorLogger->mismatchAllocDealloc(_tokenizer, callstack, varname);                    callstack.pop_back();                }                dealloctype = dealloc;                continue;            }        }        // if else switch        if (tok->str() == "if")        {            if (Token::simpleMatch(tok, std::string("if ( " + varnameStr + " )").c_str()) ||                Token::simpleMatch(tok, std::string("if ( " + varnameStr + " != 0 )").c_str()) ||                Token::simpleMatch(tok, std::string("if ( 0 != " + varnameStr + " )").c_str()))            {                addtoken("if(var)");                // Make sure the "use" will not be added                while (tok->str() != ")")                    tok = tok->next();            }            else if (Token::simpleMatch(tok, "if (") && notvar(tok->tokAt(2), varnames, true))            {                addtoken("if(!var)");            }            else            {                // Check if the condition depends on var somehow..                bool dep = false;                int parlevel = 0;                for (const Token *tok2 = tok; tok2; tok2 = tok2->next())                {                    if (tok2->str() == "(")                        ++parlevel;                    if (tok2->str() == ")")                    {                        --parlevel;                        if (parlevel <= 0)                            break;                    }                    if (Token::simpleMatch(tok2, std::string("fclose ( " + varnameStr + " )").c_str()))                    {                        addtoken("dealloc");                        addtoken(";");                        dep = true;                        break;                    }                    if ((tok2->str() != ".") &&                        Token::simpleMatch(tok2->next(), varnameStr.c_str()) &&                        !Token::simpleMatch(tok2->next(), std::string(varnameStr + " .").c_str()))                    {                        dep = true;                        break;                    }                }                addtoken((dep ? "ifv" : "if"));            }        }        if ((tok->str() == "else") || (tok->str() == "switch"))        {            addtoken(tok->aaaa());        }        if ((tok->str() == "case"))        {            addtoken("case");            addtoken(";");        }        if ((tok->str() == "default"))        {            addtoken("default");            addtoken(";");        }        // Loops..        if ((tok->str() == "for") || (tok->str() == "while"))        {            addtoken("loop");            isloop = true;        }        if ((tok->str() == "do"))        {            addtoken("do");        }        if (isloop && notvar(tok, varnames))            addtoken("!var");        // continue / break..        if (tok->str() == "continue")            addtoken("continue");        if (tok->str() == "break")            addtoken("break");        // goto..        if (tok->str() == "goto")        {            addtoken("goto");        }        // Return..        if (tok->str() == "return")        {            addtoken("return");            if (Token::simpleMatch(tok, std::string("return " + varnameStr).c_str()) ||                Token::simpleMatch(tok, std::string("return & " + varnameStr).c_str()))                addtoken("use");            if (Token::simpleMatch(tok->next(), "("))            {                for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next())                {                    if (tok2->str() == "(" || tok2->str() == ")")                        break;                    if (tok2->str() == varname)                    {                        addtoken("use");                        break;                    }                }            }            else if (Token::Match(tok, ("return strcpy|strncpy|memcpy ( " + varnameStr).c_str()))            {                addtoken("use");                tok = tok->tokAt(2);            }        }        // throw..        if (Token::Match(tok, "try|throw|catch"))            addtoken(tok->strAt(0));        // Assignment..        if (Token::Match(tok, std::string("[)=] " + varnameStr + " [+;)]").c_str()) ||            Token::Match(tok, std::string(varnameStr + " +=|-=").c_str()) ||            Token::Match(tok, std::string("+=|<< " + varnameStr + " ;").c_str()))        {            addtoken("use");        }        else if (Token::Match(tok->previous(), std::string("[;{}=(,+-*/] " + varnameStr + " [").c_str()))        {            addtoken("use_");        }        // Investigate function calls..        if (Token::Match(tok, "%var% ("))        {            // Inside class function.. if the var is passed as a parameter then            // just add a "::use"            // The "::use" means that a member function was probably called but it wasn't analyzed further            if (classmember)            {                int parlevel = 1;                for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next())                {                    if (tok2->str() == "(")                        ++parlevel;                    else if (tok2->str() == ")")                    {                        --parlevel;                        if (parlevel <= 0)                            break;                    }                    if (tok2->str() == varnameStr)                    {                        addtoken("::use");                        break;                    }                }            }            else            {                const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype, all, sz);                if (str)                    addtoken(str);            }        }        // Callback..        bool matchFirst;        if ((matchFirst = Token::Match(tok, "( %var%")) ||            Token::Match(tok, "( * %var%"))        {            int tokIdx = matchFirst ? 2 : 3;            while (Token::simpleMatch(tok->tokAt(tokIdx), ".") &&                   Token::Match(tok->tokAt(tokIdx + 1), "%var%"))                tokIdx += 2;            if (Token::simpleMatch(tok->tokAt(tokIdx), ") ("))            {                for (const Token *tok2 = tok->tokAt(tokIdx + 2); tok2; tok2 = tok2->next())                {                    if (Token::Match(tok2, "[;{]"))                        break;                    else if (tok2->str() == varname)                    {                        addtoken("use");                        break;                    }                }            }        }        // Linux lists..        if (Token::Match(tok, std::string("[=(,] & " + varnameStr + " [.[,)]").c_str()))        {            addtoken("&use");        }    }    return rethead;}void CheckMemoryLeakClass::erase(Token *begin, const Token *end){    Token::eraseTokens(begin, end);}void CheckMemoryLeakClass::simplifycode(Token *tok, bool &all){    // Replace "throw" that is not in a try block with "return"    int indentlevel = 0;    int trylevel = -1;    for (Token *tok2 = tok; tok2; tok2 = tok2->next())    {        if (tok2->str() == "{")            ++indentlevel;        else if (tok2->str() == "}")        {            --indentlevel;            if (indentlevel <= trylevel)                trylevel = -1;        }        else if (trylevel == -1 && tok2->str() == "try")            trylevel = indentlevel;        else if (trylevel == -1 && tok2->str() == "throw")            tok2->str("return");    }    // reduce the code..    bool done = false;    while (! done)    {        done = true;        for (Token *tok2 = tok; tok2; tok2 = tok2 ? tok2->next() : NULL)        {            // Delete extra ";"            while (Token::Match(tok2, "[;{}] ;"))            {                erase(tok2, tok2->tokAt(2));                done = false;            }            // Replace "{ }" with ";"            if (Token::Match(tok2->next(), "{ }"))            {                tok2->next()->str(";");                erase(tok2->next(), tok2->tokAt(3));                done = false;            }            // Delete braces around a single instruction..            if (Token::Match(tok2->next(), "{ %var% ; }"))            {                erase(tok2, tok2->tokAt(2));                erase(tok2->next()->next(), tok2->tokAt(4));                done = false;            }            if (Token::Match(tok2->next(), "{ %var% %var% ; }"))            {                erase(tok2, tok2->tokAt(2));                erase(tok2->next()->next()->next(), tok2->tokAt(5));                done = false;            }            if (Token::simpleMatch(tok2->next(), "if"))            {                // Delete empty if that is not followed by an else                if (Token::Match(tok2->next(), "if ; !!else"))                {                    erase(tok2, tok2->tokAt(2));                    done = false;                }                // Delete "if ; else ;"                else if (Token::Match(tok2->next(), "if ; else ;"))                {                    erase(tok2, tok2->tokAt(4));                    done = false;                }                // Two "if alloc ;" after one another.. perhaps only one of them can be executed each time                else if (!_settings._showAll && Token::Match(tok2, "[;{}] if alloc ; if alloc ;"))                {                    erase(tok2, tok2->tokAt(4));                    done = false;                }                // TODO Make this more generic. Delete "if ; else use ; use"                else if (Token::Match(tok2, "; if ; else assign|use ; assign|use") ||                         Token::Match(tok2, "; if assign|use ; else ; assign|use"))                {                    erase(tok2, tok2->tokAt(4));                    done = false;                }                // Reduce "if assign|dealloc|use ;" that is not followed by an else..                // If "--all" has been given these are deleted                // Otherwise, only the "if" will be deleted

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -