Memory leak: Readded some checking to classes

This commit is contained in:
Daniel Marjamäki 2009-01-14 05:58:20 +00:00
parent f33153e086
commit f7e4f13ecd
3 changed files with 45 additions and 21 deletions

View File

@ -275,7 +275,7 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
// Check if the function deallocates the variable.. // Check if the function deallocates the variable..
while (ftok && (ftok->str() != "{")) while (ftok && (ftok->str() != "{"))
ftok = ftok->next(); ftok = ftok->next();
Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype); Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype, false);
simplifycode(func); simplifycode(func);
const Token *func_ = func; const Token *func_ = func;
while (func_ && func_->str() == ";") while (func_ && func_->str() == ";")
@ -339,7 +339,7 @@ bool CheckMemoryLeakClass::notvar(const Token *tok, const char *varnames[])
Token::simpleMatch(tok, std::string(varname + " == 0").c_str())); Token::simpleMatch(tok, std::string(varname + " == 0").c_str()));
} }
Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype) Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember)
{ {
const char *varnames[2]; const char *varnames[2];
varnames[0] = varname; varnames[0] = varname;
@ -604,11 +604,19 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *>
// Investigate function calls.. // Investigate function calls..
if (Token::Match(tok, "%var% (")) if (Token::Match(tok, "%var% ("))
{
if (classmember)
{
addtoken("use");
}
else
{ {
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype);
if (str) if (str)
addtoken(str); addtoken(str);
} }
}
// Callback.. // Callback..
bool matchFirst; bool matchFirst;
@ -1108,7 +1116,7 @@ void CheckMemoryLeakClass::simplifycode(Token *tok)
// Check for memory leaks for a function variable. // Check for memory leaks for a function variable.
void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[]) void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[], bool classmember)
{ {
std::list<const Token *> callstack; std::list<const Token *> callstack;
@ -1117,7 +1125,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c
const Token *result; const Token *result;
Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype); Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype, classmember);
//tok->printOut( "getcode result" ); //tok->printOut( "getcode result" );
// Simplify the code and check if freed memory is used.. // Simplify the code and check if freed memory is used..
@ -1258,7 +1266,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_InFunction()
if (indentlevel == 0) if (indentlevel == 0)
{ {
if (Token::Match(tok, ") {")) if (Token::Match(tok, ") {"))
infunc = !classmember; infunc = true;
else if (Token::Match(tok, "[;}]")) else if (Token::Match(tok, "[;}]"))
infunc = classmember = false; infunc = classmember = false;
@ -1268,10 +1276,10 @@ void CheckMemoryLeakClass::CheckMemoryLeak_InFunction()
if (indentlevel > 0 && infunc) if (indentlevel > 0 && infunc)
{ {
if (Token::Match(tok, "[{};] %type% * %var% [;=]")) if (Token::Match(tok, "[{};] %type% * %var% [;=]"))
CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(3)); CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(3), classmember);
else if (Token::Match(tok, "[{};] %type% %type% * %var% [;=]")) else if (Token::Match(tok, "[{};] %type% %type% * %var% [;=]"))
CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(4)); CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(4), classmember);
} }
} }
} }
@ -1503,7 +1511,7 @@ Token * CheckMemoryLeakClass::functionParameterCode(const Token *ftok, int param
// Return the code.. // Return the code..
AllocType alloc = No, dealloc = No; AllocType alloc = No, dealloc = No;
std::list<const Token *> callstack; std::list<const Token *> callstack;
Token *code = getcode(ftok, callstack, parname, alloc, dealloc); Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false);
simplifycode(code); simplifycode(code);
return code; return code;
} }

View File

@ -60,7 +60,7 @@ private:
void CheckMemoryLeak_ClassMembers_ParseClass(const Token *tok1, std::vector<const char *> &classname); void CheckMemoryLeak_ClassMembers_ParseClass(const Token *tok1, std::vector<const char *> &classname);
void CheckMemoryLeak_ClassMembers(); void CheckMemoryLeak_ClassMembers();
void CheckMemoryLeak_InFunction(); void CheckMemoryLeak_InFunction();
void CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[]); void CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[], bool classmember);
/** /**
* Simplify code e.g. by replacing empty "{ }" with ";" * Simplify code e.g. by replacing empty "{ }" with ";"
@ -87,7 +87,7 @@ private:
* @return Newly allocated token array. Caller needs to release reserved * @return Newly allocated token array. Caller needs to release reserved
* memory by calling Tokenizer::deleteTokens(returnValue); * memory by calling Tokenizer::deleteTokens(returnValue);
*/ */
Token *getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype); Token *getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember);
bool notvar(const Token *tok, const char *varnames[]); bool notvar(const Token *tok, const char *varnames[]);
void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype); void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype);
void MismatchError(const Token *Tok1, const std::list<const Token *> &callstack, const char varname[]); void MismatchError(const Token *Tok1, const std::list<const Token *> &callstack, const char varname[]);

View File

@ -135,6 +135,7 @@ private:
TEST_CASE(class2); TEST_CASE(class2);
// TODO TEST_CASE( class3 ); // TODO TEST_CASE( class3 );
TEST_CASE(class4); TEST_CASE(class4);
TEST_CASE(class5);
TEST_CASE(throw1); TEST_CASE(throw1);
TEST_CASE(throw2); TEST_CASE(throw2);
@ -1234,28 +1235,43 @@ private:
void class4() void class4()
{ {
check("struct MONITOR_POST;\n" check("struct ABC;\n"
"class MonitorClient\n" "class Fred\n"
"{\n" "{\n"
"private:\n" "private:\n"
" void addPost(MONITOR_POST *MonitorPost);\n" " void addAbc(ABC *abc);\n"
"public:\n" "public:\n"
" void click();\n" " void click();\n"
"};\n" "};\n"
"\n" "\n"
"void MonitorClient::addPost(MONITOR_POST* MonitorPost)\n" "void Fred::addAbc(ABC* abc)\n"
"{\n" "{\n"
" _pMonitorPosts->Add(MonitorPost);\n" " AbcPosts->Add(abc);\n"
"}\n" "}\n"
"\n" "\n"
"void MonitorClient::click()\n" "void Fred::click()\n"
"{\n" "{\n"
" MONITOR_POST *NewMeasurePost = new MONITOR_POST;\n" " ABC *p = new ABC;\n"
" addPost( NewMeasurePost );\n" " addAbc( p );\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void class5()
{
check("class Fred\n"
"{\n"
"public:\n"
" void foo();\n"
"};\n"
"\n"
"void Fred::foo()\n"
"{\n"
" char *str = new char[100];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:10]: Memory leak: str\n", errout.str());
}