Memory leaks: Added and fixed testcase TestMemleakInClass::class13

This commit is contained in:
Daniel Marjamäki 2009-10-23 20:04:47 +02:00
parent 88070b044b
commit 2c8a418c7e
2 changed files with 42 additions and 7 deletions

View File

@ -2095,11 +2095,15 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
CheckMemoryLeak::AllocType Alloc = CheckMemoryLeak::No;
CheckMemoryLeak::AllocType Dealloc = CheckMemoryLeak::No;
bool allocInConstructor = false;
bool deallocInDestructor = false;
// Loop through all tokens. Inspect member functions
int indent_ = 0;
const Token *functionToken = Tokenizer::findClassFunction(_tokenizer->tokens(), classname, "~| %var%", indent_);
while (functionToken)
{
const bool constructor(Token::Match(functionToken, (classname + std::string(" :: ") + classname + " (").c_str()));
const bool destructor(functionToken->tokAt(2)->str() == "~");
int indent = 0;
@ -2130,6 +2134,9 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
AllocType alloc = getAllocationType(tok->tokAt((indent > 0) ? 2 : 3), 0);
if (alloc != CheckMemoryLeak::No)
{
if (constructor)
allocInConstructor = true;
if (Alloc != No && Alloc != alloc)
alloc = CheckMemoryLeak::Many;
@ -2148,12 +2155,9 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
if (indent == 0)
continue;
if (!destructor)
continue;
// Function call..
if (Token::Match(tok, "[{};] %var% ("))
return;
// Function call in destructor.. possible deallocation
if (destructor && Token::Match(tok, "[{};] %var% ("))
deallocInDestructor = true;
// Deallocate..
const char *varnames[3] = { "var", 0, 0 };
@ -2167,6 +2171,9 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
}
if (dealloc != CheckMemoryLeak::No)
{
if (destructor)
deallocInDestructor = true;
if (Dealloc != CheckMemoryLeak::No && Dealloc != dealloc)
dealloc = CheckMemoryLeak::Many;
@ -2186,7 +2193,11 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
functionToken = Tokenizer::findClassFunction(functionToken->next(), classname, "~| %var%", indent_);
}
if (Alloc != CheckMemoryLeak::No && Dealloc == CheckMemoryLeak::No)
if (allocInConstructor && !deallocInDestructor)
{
memoryLeak(tokVarname, (std::string(classname) + "::" + varname).c_str(), Alloc, true);
}
else if (Alloc != CheckMemoryLeak::No && Dealloc == CheckMemoryLeak::No)
{
memoryLeak(tokVarname, (std::string(classname) + "::" + varname).c_str(), Alloc, true);
}

View File

@ -2468,6 +2468,7 @@ private:
TEST_CASE(class10);
TEST_CASE(class11);
TEST_CASE(class12);
TEST_CASE(class13);
TEST_CASE(staticvar);
@ -2711,6 +2712,29 @@ private:
ASSERT_EQUALS("[test.cpp:4]: (possible error) Memory leak: A::p\n", errout.str());
}
void class13()
{
check("class A\n"
"{\n"
"private:\n"
" int *p;\n"
"public:\n"
" A();\n"
" ~A();\n"
" void foo();"
"};\n"
"\n"
"A::A()\n"
"{ }\n"
"\n"
"A::~A()\n"
"{ }\n"
"\n"
"void A::foo()\n"
"{ p = new int[10]; delete [] p; }\n", true);
ASSERT_EQUALS("", errout.str());
}
void staticvar()
{