Memory leaks: Better handling of "realloc". Fixing bug [ 2395262 ]

This commit is contained in:
Daniel Marjamäki 2008-12-06 13:33:22 +00:00
parent 202c613e70
commit 7c32b7b2bb
3 changed files with 68 additions and 3 deletions

View File

@ -135,6 +135,32 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType( const T
return No; return No;
} }
CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetReallocationType( const TOKEN *tok2 )
{
// What we may have...
// * var = (char *)realloc(..;
if ( tok2 && tok2->str() == "(" )
{
while ( tok2 && tok2->str() != ")" )
tok2 = tok2->next;
tok2 = tok2 ? tok2->next : NULL;
}
if ( ! tok2 )
return No;
if ( TOKEN::Match(tok2, "realloc") )
return Malloc;
// GTK memory reallocation..
if ( TOKEN::Match(tok2, "g_realloc|g_try_realloc|g_renew|g_try_renew") )
return gMalloc;
return No;
}
CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const char *varnames[] ) CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const char *varnames[] )
{ {
if ( TOKEN::Match(tok, "delete %var1% ;", varnames) ) if ( TOKEN::Match(tok, "delete %var1% ;", varnames) )
@ -167,7 +193,7 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list<const
if (TOKEN::Match(tok,"if") || TOKEN::Match(tok,"for") || TOKEN::Match(tok,"while")) if (TOKEN::Match(tok,"if") || TOKEN::Match(tok,"for") || TOKEN::Match(tok,"while"))
return 0; return 0;
if (GetAllocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No) if (GetAllocationType(tok)!=No || GetReallocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No)
return 0; return 0;
if ( callstack.size() > 2 ) if ( callstack.size() > 2 )
@ -337,6 +363,16 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
{ {
AllocType alloc = GetAllocationType(tok->tokAt(3)); AllocType alloc = GetAllocationType(tok->tokAt(3));
if ( alloc == No )
{
alloc = GetReallocationType( tok->tokAt(3) );
if ( alloc != No )
{
addtoken( "dealloc" );
addtoken( ";" );
}
}
// If "--all" hasn't been given, don't check classes.. // If "--all" hasn't been given, don't check classes..
if ( alloc == New && ! _settings._showAll ) if ( alloc == New && ! _settings._showAll )
{ {

View File

@ -95,6 +95,7 @@ private:
const char * call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ); const char * call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype );
AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]); AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]);
AllocType GetAllocationType( const TOKEN *tok2 ); AllocType GetAllocationType( const TOKEN *tok2 );
AllocType GetReallocationType( const TOKEN *tok2 );
bool isclass( const TOKEN *typestr ); bool isclass( const TOKEN *typestr );
const Tokenizer *_tokenizer; const Tokenizer *_tokenizer;

View File

@ -123,6 +123,9 @@ private:
TEST_CASE( linux_list_1 ); TEST_CASE( linux_list_1 );
TEST_CASE( sizeof1 ); TEST_CASE( sizeof1 );
TEST_CASE( realloc1 );
TEST_CASE( realloc2 );
} }
@ -965,6 +968,31 @@ private:
ASSERT_EQUALS( std::string("[test.cpp:12]: Memory leak: s2\n"), err ); ASSERT_EQUALS( std::string("[test.cpp:12]: Memory leak: s2\n"), err );
} }
void realloc1()
{
check( "void foo()\n"
"{\n"
" char *a = (char *)malloc(10);\n"
" a = realloc(a, 100);\n"
"}\n" );
ASSERT_EQUALS( std::string("[test.cpp:5]: Memory leak: a\n"), errout.str() );
}
void realloc2()
{
check( "void foo()\n"
"{\n"
" char *a = (char *)malloc(10);\n"
" a = (char *)realloc(a, 100);\n"
" free(a);\n"
"}\n" );
ASSERT_EQUALS( std::string(""), errout.str() );
}
}; };
REGISTER_TEST( TestMemleak ) REGISTER_TEST( TestMemleak )