Memory leaks: Removed the experimental checking using ExecutionPath.

This commit is contained in:
Daniel Marjamäki 2010-12-06 21:46:18 +01:00
parent b705a9cbdd
commit 26864dd011
3 changed files with 0 additions and 271 deletions

View File

@ -3040,173 +3040,6 @@ void CheckMemoryLeakStructMember::check()
/** @brief Experimental class for detecting memory leaks. The ExecutionPath functionality is used */
class CheckLocalLeaks : public ExecutionPath
{
public:
/** Startup constructor */
CheckLocalLeaks(Check *c) : ExecutionPath(c, 0), allocated(false)
{
}
/** Debugging : print checks */
static void printOut(const std::list<ExecutionPath *> &checks)
{
std::ostringstream ostr;
ostr << "CheckLocalLeaks::printOut" << std::endl;
for (std::list<ExecutionPath *>::const_iterator it = checks.begin(); it != checks.end(); ++it)
{
CheckLocalLeaks *c = dynamic_cast<CheckLocalLeaks *>(*it);
if (c)
{
ostr << std::hex << c << ": varId=" << c->varId << " allocated=" << (c->allocated ? "true" : "false") << std::endl;
}
}
std::cout << ostr.str();
}
private:
ExecutionPath *copy()
{
return new CheckLocalLeaks(*this);
}
/** start checking of given variable */
CheckLocalLeaks(Check *c, unsigned int v, const std::string &s) : ExecutionPath(c, v), allocated(false), varname(s)
{
}
/** is other execution path equal? */
bool is_equal(const ExecutionPath *e) const
{
const CheckLocalLeaks *c = static_cast<const CheckLocalLeaks *>(e);
return (allocated == c->allocated && varname == c->varname);
}
/** Is variable allocated? */
bool allocated;
/** Name of variable */
const std::string varname;
/** no implementation => compiler error if used */
void operator=(const CheckLocalLeaks &);
/** Allocation is detected */
static void alloc(std::list<ExecutionPath *> &checks, const unsigned int varid)
{
if (varid == 0)
return;
std::list<ExecutionPath *>::iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
CheckLocalLeaks *C = dynamic_cast<CheckLocalLeaks *>(*it);
if (C && C->varId == varid)
C->allocated = true;
}
}
/** Deallocation is detected */
static void dealloc(std::list<ExecutionPath *> &checks, const Token *tok)
{
if (tok->varId() == 0)
return;
std::list<ExecutionPath *>::iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
CheckLocalLeaks *C = dynamic_cast<CheckLocalLeaks *>(*it);
if (C && C->varId == tok->varId())
C->allocated = false;
}
}
/** return */
static void ret(const std::list<ExecutionPath *> &checks, const Token *tok)
{
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it)
{
CheckLocalLeaks *C = dynamic_cast<CheckLocalLeaks *>(*it);
if (C && C->allocated)
{
CheckMemoryLeakInFunction *checkMemleak = reinterpret_cast<CheckMemoryLeakInFunction *>(C->owner);
if (checkMemleak)
{
checkMemleak->memleakError(tok, C->varname);
break;
}
}
}
}
/** parse the tokens */
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
{
//std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl;
//printOut(checks);
if (!Token::Match(tok.previous(), "[;{}]"))
return &tok;
if (Token::Match(&tok, "%type% * %var% ;"))
{
const Token * vartok = tok.tokAt(2);
if (vartok->varId() != 0)
checks.push_back(new CheckLocalLeaks(owner, vartok->varId(), vartok->str()));
return vartok->next();
}
if (Token::Match(&tok, "%var% = new"))
{
alloc(checks, tok.varId());
// goto end of statement
const Token *tok2 = &tok;
while (tok2 && tok2->str() != ";")
tok2 = tok2->next();
return tok2;
}
if (Token::Match(&tok, "delete %var% ;"))
{
dealloc(checks, tok.next());
return tok.tokAt(2);
}
if (Token::Match(&tok, "delete [ ] %var% ;"))
{
dealloc(checks, tok.tokAt(3));
return tok.tokAt(4);
}
if (tok.str() == "return")
{
ret(checks, &tok);
}
return &tok;
}
/** going out of scope - all execution paths end */
void end(const std::list<ExecutionPath *> &checks, const Token *tok) const
{
ret(checks, tok);
}
};
void CheckMemoryLeakInFunction::localleaks()
{
// Check this scope..
CheckLocalLeaks c(this);
checkExecutionPaths(_tokenizer->tokens(), &c);
}
#include "checkuninitvar.h" // CheckUninitVar::analyse
void CheckMemoryLeakNoVar::check()

View File

@ -201,9 +201,6 @@ public:
/** @brief Perform checking */
void check();
/** @brief experimental: checking via ExecutionPath */
void localleaks();
/**
* Checking for a memory leak caused by improper realloc usage.
*/

View File

@ -27,107 +27,6 @@
extern std::ostringstream errout;
class TestLocalLeaks : private TestFixture
{
public:
TestLocalLeaks() : TestFixture("TestLocalLeaks")
{ }
private:
void run()
{
TEST_CASE(test1);
TEST_CASE(test2);
TEST_CASE(test3);
TEST_CASE(test4);
TEST_CASE(test5);
}
void check(const char code[])
{
// Clear the error buffer..
errout.str("");
Settings settings;
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.setVarId();
tokenizer.simplifyTokenList();
// Check for memory leaks..
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this);
checkMemoryLeak.localleaks();
}
void test1()
{
check("void foo()\n"
"{\n"
" char *p = new char[100];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n", errout.str());
}
void test2()
{
check("void foo()\n"
"{\n"
" char *p = new char[100];\n"
" delete [] p;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void test3()
{
check("void foo(int x)\n"
"{\n"
" char *p = 0;\n"
" if (x == 1)\n"
" p = new char[100];\n"
" if (x == 2)\n"
" delete [] p;\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:8]: (error) Memory leak: p\n", errout.str());
ASSERT_EQUALS("", errout.str());
}
void test4()
{
check("void foo(int x)\n"
"{\n"
" char *p = 0;\n"
" if (x == 1)\n"
" p = new char[100];\n"
" if (x == 1)\n"
" delete [] p;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void test5() //#ticket 1879
{
check("void test()\n"
"{\n"
" int *a = new int[10];\n"
" try\n"
" {\n"
" }\n"
" catch(...)\n"
" {\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: a\n",errout.str());
}
};
static TestLocalLeaks testLocalLeaks;
class TestMemleak : private TestFixture
{
public: