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

📄 checkmemoryleak.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            tok2->str("use");        else if (tok2->str() == "dealloc_")            tok2->str("dealloc");        else if (tok2->str() == "realloc")        {            tok2->str("dealloc");            tok2->insertToken("alloc");            tok2->insertToken(";");        }    }    simplifycode(tok, all);    //tok->printOut("simplifycode result");    // If the variable is not allocated at all => no memory leak    if (Token::findmatch(tok, "alloc") == 0)    {        Tokenizer::deleteTokens(tok);        return;    }    // TODO : handle "goto"    if (Token::findmatch(tok, "goto"))    {        Tokenizer::deleteTokens(tok);        return;    }    if ((result = Token::findmatch(tok, "loop alloc ;")) != NULL)    {        MemoryLeak(result, varname, alloctype, all);    }    else if ((result = Token::findmatch(tok, "alloc ; if break|continue|return ;")) != NULL             && Token::findmatch(tok, "dealloc ; alloc ; if continue ;") == NULL)    {        MemoryLeak(result->tokAt(3), varname, alloctype, all);    }    else if (_settings._showAll && (result = Token::findmatch(tok, "alloc ; ifv break|continue|return ;")) != NULL)    {        MemoryLeak(result->tokAt(3), varname, alloctype, all);    }    else if ((result = Token::findmatch(tok, "alloc ; alloc|assign|return ;")) != NULL)    {        MemoryLeak(result->tokAt(2), varname, alloctype, all);    }    else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL)    {        _errorLogger->deallocDealloc(_tokenizer, result->tokAt(2), varname);    }    else if (! Token::findmatch(tok, "dealloc") &&             ! Token::findmatch(tok, "use") &&             ! Token::findmatch(tok, "return use ;"))    {        const Token *last = tok;        while (last->next())            last = last->next();        MemoryLeak(last, varname, alloctype, all);    }    // detect cases that "simplifycode" don't handle well..    else if (_settings._debug)    {        Token *first = tok;        while (first && first->str() == ";")            first = first->next();        bool noerr = false;        noerr |= Token::Match(first, "alloc ; }");        noerr |= Token::Match(first, "alloc ; dealloc ; }");        noerr |= Token::Match(first, "alloc ; return use ; }");        noerr |= Token::Match(first, "alloc ; use ; }");        noerr |= Token::Match(first, "alloc ; use ; return ; }");        noerr |= Token::Match(first, "if alloc ; dealloc ; }");        noerr |= Token::Match(first, "if alloc ; return use ; }");        noerr |= Token::Match(first, "if alloc ; use ; }");        noerr |= Token::Match(first, "alloc ; ifv return ; dealloc ; }");        noerr |= Token::Match(first, "alloc ; if return ; dealloc; }");        // Unhandled case..        if (! noerr)        {            std::cout << "Token listing..\n  ";            for (const Token *tok2 = tok; tok2; tok2 = tok2->next())                std::cout << " " << tok2->str();            std::cout << "\n";        }    }    Tokenizer::deleteTokens(tok);}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// Checks for memory leaks inside function..//---------------------------------------------------------------------------void CheckMemoryLeakClass::CheckMemoryLeak_InFunction(){    bool classmember = false;    bool infunc = false;    int indentlevel = 0;    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())    {        if (tok->str() == "{")            ++indentlevel;        else if (tok->str() == "}")            --indentlevel;        if (tok->str() == "::")            classmember = true;        // In function..        if (indentlevel == 0)        {            if (Token::Match(tok, ") {"))                infunc = true;            else if (Token::Match(tok, "[;}]"))                infunc = classmember = false;        }        // Declare a local variable => Check        if (indentlevel > 0 && infunc)        {            unsigned int sz = _tokenizer->SizeOfType(tok->strAt(1));            if (sz < 1)                sz = 1;            if (Token::Match(tok, "[{};] %type% * %var% [;=]"))                CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(3), classmember, sz);            else if (Token::Match(tok, "[{};] %type% %type% * %var% [;=]"))                CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(4), classmember, sz);        }    }}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// Checks for memory leaks in classes..//---------------------------------------------------------------------------void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers(){    int indentlevel = 0;    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())    {        if (tok->str() == "{")            ++indentlevel;        else if (tok->str() == "}")            --indentlevel;        else if (indentlevel == 0 && Token::Match(tok, "class %var% [{:]"))        {            std::vector<const char *> classname;            classname.push_back(tok->strAt(1));            CheckMemoryLeak_ClassMembers_ParseClass(tok, classname);        }    }}void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_ParseClass(const Token *tok1, std::vector<const char *> &classname){    // Go into class.    while (tok1 && tok1->str() != "{")        tok1 = tok1->next();    if (tok1)        tok1 = tok1->next();    int indentlevel = 0;    for (const Token *tok = tok1; tok; tok = tok->next())    {        if (tok->str() == "{")            ++indentlevel;        else if (tok->str() == "}")        {            --indentlevel;            if (indentlevel < 0)                return;        }        // Only parse this particular class.. not subclasses        if (indentlevel > 0)            continue;        // Declaring subclass.. recursive checking        if (Token::Match(tok, "class %var% [{:]"))        {            classname.push_back(tok->strAt(1));            CheckMemoryLeak_ClassMembers_ParseClass(tok, classname);            classname.pop_back();        }        // Declaring member variable.. check allocations and deallocations        if (Token::Match(tok->next(), "%type% * %var% ;"))        {            // No false positives for auto deallocated classes..            if (_settings.isAutoDealloc(tok->strAt(1)))                continue;            if (tok->isName() || Token::Match(tok, "[;}]"))            {                if (_settings._showAll || !isclass(tok->tokAt(1)))                    CheckMemoryLeak_ClassMembers_Variable(classname, tok->tokAt(3));            }        }    }}void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable(const std::vector<const char *> &classname, const Token *tokVarname){    const char *varname = tokVarname->strAt(0);    // Function pattern.. Check if member function    std::ostringstream fpattern;    for (unsigned int i = 0; i < classname.size(); i++)    {        fpattern << classname[i] << " :: ";    }    fpattern << "%var% (";    // Destructor pattern.. Check if class destructor..    std::ostringstream destructor;    for (unsigned int i = 0; i < classname.size(); i++)    {        destructor << classname[i] << " :: ";    }    destructor << "~ " << classname.back() << " (";    // Pattern used in member function. "Var = ..."    std::ostringstream varname_eq;    varname_eq << varname << " =";    // Full variable name..    std::ostringstream FullVariableName;    for (unsigned int i = 0; i < classname.size(); i++)        FullVariableName << classname[i] << "::";    FullVariableName << varname;    // Check if member variable has been allocated and deallocated..    AllocType Alloc = No;    AllocType Dealloc = No;    // Loop through all tokens. Inspect member functions    bool memberfunction = false;    int indentlevel = 0;    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())    {        if (tok->str() == "{")            ++indentlevel;        else if (tok->str() == "}")            --indentlevel;        // Set the 'memberfunction' variable..        if (indentlevel == 0)        {            if (Token::Match(tok, "[;}]"))                memberfunction = false;            else if (Token::Match(tok, fpattern.str().c_str()) || Token::Match(tok, destructor.str().c_str()))                memberfunction = true;        }        // Parse member function..        if (indentlevel > 0 && memberfunction)        {            // Allocate..            if (Token::Match(tok, varname_eq.str().c_str()))            {                AllocType alloc = GetAllocationType(tok->tokAt(2));                if (alloc != No)                {                    if (Alloc != No && Alloc != alloc)                        alloc = Many;                    std::list<const Token *> callstack;                    if (alloc != Many && Dealloc != No && Dealloc != Many && Dealloc != alloc)                    {                        callstack.push_back(tok);                        _errorLogger->mismatchAllocDealloc(_tokenizer, callstack, FullVariableName.str());                        callstack.pop_back();                    }                    Alloc = alloc;                }            }            // Deallocate..            const char *varnames[3] = { "var", 0, 0 };            varnames[0] = varname;            AllocType dealloc = GetDeallocationType(tok, varnames);            if (dealloc == No)            {                varnames[0] = "this";                varnames[1] = varname;                dealloc = GetDeallocationType(tok, varnames);            }            if (dealloc != No)            {                if (Dealloc != No && Dealloc != dealloc)                    dealloc = Many;                std::list<const Token *> callstack;                if (dealloc != Many && Alloc != No &&  Alloc != Many && Alloc != dealloc)                {                    callstack.push_back(tok);                    _errorLogger->mismatchAllocDealloc(_tokenizer, callstack, FullVariableName.str());                    callstack.pop_back();                }                Dealloc = dealloc;            }        }    }    if (Alloc != No && Dealloc == No)    {        MemoryLeak(tokVarname, FullVariableName.str().c_str(), Alloc, true);    }}//---------------------------------------------------------------------------// Checks for memory leaks..//---------------------------------------------------------------------------void CheckMemoryLeakClass::CheckMemoryLeak(){    _listAllocFunc.clear();    // Check for memory leaks inside functions..    CheckMemoryLeak_InFunction();    // Check that all class members are deallocated..    if (_settings._showAll)        CheckMemoryLeak_ClassMembers();}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// Non-recursive function analysis//---------------------------------------------------------------------------Token * CheckMemoryLeakClass::functionParameterCode(const Token *ftok, int parameter){    int param = 1;  // First parameter has index 1    // Extract the code for specified parameter...    for (; ftok; ftok = ftok->next())    {        if (ftok->str() == ")")            break;        if (ftok->str() == ",")        {            ++param;            if (param > parameter)                break;        }        if (param != parameter)            continue;        if (! Token::Match(ftok, "* %var% [,)]"))            continue;        // Extract and return the code for this parameter..        const char *parname = ftok->strAt(1);        // Goto function implementation..        while (ftok && ftok->str() != "{")            ftok = ftok->next();        ftok = ftok ? ftok->next() : NULL;        // Return the code..        AllocType alloc = No, dealloc = No;        bool all = false;        std::list<const Token *> callstack;        Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false, all, 1);        simplifycode(code, all);        return code;    }    return NULL;}

⌨️ 快捷键说明

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