Memory leak: Readded some checking to classes
This commit is contained in:
parent
f33153e086
commit
f7e4f13ecd
|
@ -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;
|
||||||
|
@ -605,9 +605,17 @@ 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% ("))
|
||||||
{
|
{
|
||||||
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype);
|
if (classmember)
|
||||||
if (str)
|
{
|
||||||
addtoken(str);
|
addtoken("use");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype);
|
||||||
|
if (str)
|
||||||
|
addtoken(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback..
|
// Callback..
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[]);
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue