📄 checkmemoryleak.cpp
字号:
{ 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 + -