diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index 181e00ad9..39589e740 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -186,9 +186,7 @@ AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const cha } //-------------------------------------------------------------------------- -static std::list callstack; - -const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, const char *varnames[] ) +const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ) { if (Match(tok,"if") || Match(tok,"for") || Match(tok,"while")) return 0; @@ -197,9 +195,9 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, const char *varn return 0; const char *funcname = tok->str; - if ( std::find(callstack.begin(), callstack.end(), std::string(funcname)) != callstack.end() ) + if ( std::find(callstack.begin(), callstack.end(), tok) != callstack.end() ) return "use"; - callstack.push_back(funcname); + callstack.push_back(tok); int par = 1; int parlevel = 0; @@ -227,7 +225,7 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, const char *varn // Check if the function deallocates the variable.. while ( ftok && ! Match(ftok,"{") ) ftok = ftok->next; - TOKEN *func = getcode( Tokenizer::gettok(ftok,1), parname ); + TOKEN *func = getcode( Tokenizer::gettok(ftok,1), callstack, parname, alloctype, dealloctype ); simplifycode( func ); const char *ret = 0; if (findmatch(func, "goto")) @@ -246,9 +244,11 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, const char *varn //-------------------------------------------------------------------------- -void CheckMemoryLeakClass::MismatchError( const TOKEN *Tok1, const char varname[] ) +void CheckMemoryLeakClass::MismatchError( const TOKEN *Tok1, const std::list &callstack, const char varname[] ) { - std::ostringstream errmsg; + std::ostringstream errmsg; + for ( std::list::const_iterator tok = callstack.begin(); tok != callstack.end(); ++tok ) + errmsg << FileLine(*tok, _tokenizer) << " -> "; errmsg << FileLine(Tok1, _tokenizer) << ": Mismatching allocation and deallocation: " << varname; ReportErr( errmsg.str() ); } @@ -290,7 +290,7 @@ extern bool ShowAll; * varname - name of variable */ -TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, const char varname[]) +TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype) { const char *varnames[2]; varnames[0] = varname; @@ -311,9 +311,6 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, const char varname[]) rettail=newtok; \ } - AllocType alloctype = No; - AllocType dealloctype = No; - bool isloop = false; int indentlevel = 0; @@ -360,9 +357,9 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, const char varname[]) { addtoken("alloc"); if (alloctype!=No && alloctype!=alloc) - MismatchError(tok, varname); + MismatchError(tok, callstack, varname); if (dealloctype!=No && dealloctype!=alloc) - MismatchError(tok, varname); + MismatchError(tok, callstack, varname); alloctype = alloc; } } @@ -372,9 +369,9 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, const char varname[]) { addtoken("dealloc"); if (alloctype!=No && alloctype!=dealloc) - MismatchError(tok, varname); + MismatchError(tok, callstack, varname); if (dealloctype!=No && dealloctype!=dealloc) - MismatchError(tok, varname); + MismatchError(tok, callstack, varname); dealloctype = dealloc; } @@ -453,7 +450,7 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, const char varname[]) // Investigate function calls.. if ( Match(tok, "%var% (") ) { - const char *str = call_func(tok, varnames); + const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); if ( str ) addtoken( str ); } @@ -766,10 +763,13 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) // Simpler but less powerful than "CheckMemoryLeak_CheckScope_All" void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] ) -{ - callstack.clear(); +{ + std::list callstack; - TOKEN *tok = getcode( Tok1, varname ); + AllocType alloctype = No; + AllocType dealloctype = No; + + TOKEN *tok = getcode( Tok1, callstack, varname, alloctype, dealloctype ); // If the variable is not allocated at all => no memory leak if (findmatch(tok, "alloc") == 0) @@ -1008,11 +1008,12 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable( const std::vec { AllocType alloc = GetAllocationType( Tokenizer::gettok( tok, 2 ) ); if ( alloc != No ) - { + { + std::list callstack; if ( Dealloc != No && Dealloc != alloc ) - MismatchError( tok, FullVariableName.str().c_str() ); + MismatchError( tok, callstack, FullVariableName.str().c_str() ); if ( Alloc != No && Alloc != alloc ) - MismatchError( tok, FullVariableName.str().c_str() ); + MismatchError( tok, callstack, FullVariableName.str().c_str() ); Alloc = alloc; } } @@ -1022,11 +1023,12 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable( const std::vec varnames[0] = varname; AllocType dealloc = GetDeallocationType( tok, varnames ); if ( dealloc != No ) - { + { + std::list callstack; if ( Dealloc != No && Dealloc != dealloc ) - MismatchError( tok, FullVariableName.str().c_str() ); + MismatchError( tok, callstack, FullVariableName.str().c_str() ); if ( Alloc != No && Alloc != dealloc ) - MismatchError( tok, FullVariableName.str().c_str() ); + MismatchError( tok, callstack, FullVariableName.str().c_str() ); Dealloc = dealloc; } } diff --git a/CheckMemoryLeak.h b/CheckMemoryLeak.h index 8a3192f4a..cc5ed15ac 100644 --- a/CheckMemoryLeak.h +++ b/CheckMemoryLeak.h @@ -25,8 +25,9 @@ /** \brief Check for memory leaks */ -#include #include "tokenize.h" +#include +#include enum AllocType { No, Malloc, gMalloc, New, NewA }; @@ -46,13 +47,13 @@ private: void simplifycode(TOKEN *tok); void erase(TOKEN *begin, const TOKEN *end); - TOKEN *getcode(const TOKEN *tok, const char varname[]); + TOKEN *getcode(const TOKEN *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype); bool notvar(const TOKEN *tok, const char *varnames[]); void instoken(TOKEN *tok, const char str[]); void MemoryLeak( const TOKEN *tok, const char varname[] ); - void MismatchError( const TOKEN *Tok1, const char varname[] ); - const char * call_func( const TOKEN *tok, const char *varnames[] ); - AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[] ); + void MismatchError( const TOKEN *Tok1, const std::list &callstack, const char varname[] ); + const char * call_func( const TOKEN *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ); + AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]); AllocType GetAllocationType( const TOKEN *tok2 ); bool isclass( const std::string &typestr ); diff --git a/testmemleak.cpp b/testmemleak.cpp index 4c7d1e0fc..c47341bf3 100644 --- a/testmemleak.cpp +++ b/testmemleak.cpp @@ -110,7 +110,7 @@ private: TEST_CASE( func2 ); TEST_CASE( func3 ); TEST_CASE( func4 ); - // TODO TEST_CASE( func5 ); + TEST_CASE( func5 ); TEST_CASE( class1 ); TEST_CASE( class2 ); @@ -710,8 +710,9 @@ private: "{\n" " char *p = new char[100];\n" " foo(p);\n" - "}\n" ); - ASSERT_EQUALS( std::string("mismatching allocation and deallocation"), errout.str() ); + "}\n" ); + std::string err( errout.str() ); + ASSERT_EQUALS( std::string("[test.cpp:9] -> [test.cpp:3]: Mismatching allocation and deallocation: str\n"), err ); }