Memory leak: Handling function that can't be traced into

This commit is contained in:
Daniel Marjamäki 2009-02-08 11:59:04 +00:00
parent cb5974e94e
commit 0361c9d338
2 changed files with 32 additions and 18 deletions

View File

@ -196,7 +196,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const
const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz) const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz)
{ {
// Keywords that are not function calls.. // Keywords that are not function calls..
if (Token::Match(tok, "if|for|while")) if (Token::Match(tok, "if|for|while|return|switch"))
return 0; return 0;
// String functions that are not allocating nor deallocating memory.. // String functions that are not allocating nor deallocating memory..
@ -221,7 +221,7 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
if (callstack.size() > 2) if (callstack.size() > 2)
return "dealloc_"; return "dealloc_";
const char *funcname = tok->aaaa(); const std::string funcname(tok->str());
for (std::list<const Token *>::const_iterator it = callstack.begin(); it != callstack.end(); ++it) for (std::list<const Token *>::const_iterator it = callstack.begin(); it != callstack.end(); ++it)
{ {
if ((*it)->str() == funcname) if ((*it)->str() == funcname)
@ -250,7 +250,9 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
{ {
--parlevel; --parlevel;
if (parlevel < 1) if (parlevel < 1)
return NULL; {
return _settings._showAll ? 0 : "callfunc";
}
} }
if (parlevel == 1) if (parlevel == 1)
@ -259,7 +261,7 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
++par; ++par;
if (Token::Match(tok, pattern.c_str())) if (Token::Match(tok, pattern.c_str()))
{ {
const Token *ftok = _tokenizer->GetFunctionTokenByName(funcname); const Token *ftok = _tokenizer->GetFunctionTokenByName(funcname.c_str());
const char *parname = Tokenizer::getParameterName(ftok, par); const char *parname = Tokenizer::getParameterName(ftok, par);
if (! parname) if (! parname)
return "recursive"; return "recursive";

View File

@ -188,7 +188,8 @@ private:
TEST_CASE(malloc_constant_1); // Check that the malloc constant matches the type TEST_CASE(malloc_constant_1); // Check that the malloc constant matches the type
// Calls to unknown functions.. they may throw exception, quit the program, etc // Calls to unknown functions.. they may throw exception, quit the program, etc
// TODO TEST_CASE(unknownFunction1); TEST_CASE(unknownFunction1);
// TODO TEST_CASE(unknownFunction2);
} }
@ -1828,20 +1829,31 @@ private:
void unknownFunction1() void unknownFunction1()
{ {
const char code[] = "void foo()\n" check("void foo()\n"
"{\n" "{\n"
" int *p = new int[100];\n" " int *p = new int[100];\n"
" if (abc)\n" " if (abc)\n"
" {\n" " {\n"
" delete [] p;\n" " delete [] p;\n"
" ThrowException();\n" " ThrowException();\n"
" }\n" " }\n"
" delete [] p;\n" " delete [] p;\n"
"}\n"; "}\n");
check(code, false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check(code, true); }
ASSERT_EQUALS("[test.cpp:9]: (all) Deallocating a deallocated pointer: p\n", errout.str());
void unknownFunction2()
{
check("void foo()\n"
"{\n"
" int *p = new int[100];\n"
" if (abc)\n"
" {\n"
" delete [] p;\n"
" ThrowException();\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9] (error) Memory leak: p\n", errout.str());
} }
}; };