Memory leak: Began work for parsing into subfunctions.
This commit is contained in:
parent
26bfab1c7e
commit
8fce5d39e5
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <stdlib.h> // free
|
#include <stdlib.h> // free
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
static TOKEN *getcode(const TOKEN *tok, const char varname[]);
|
||||||
|
|
||||||
static bool isclass( const std::string &typestr )
|
static bool isclass( const std::string &typestr )
|
||||||
{
|
{
|
||||||
|
@ -174,7 +175,61 @@ static AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[] )
|
||||||
|
|
||||||
return No;
|
return No;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static std::list<std::string> callstack;
|
||||||
|
|
||||||
|
static const char * call_func( const TOKEN *tok, const char *varnames[] )
|
||||||
|
{
|
||||||
|
if (GetAllocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char *funcname = tok->str;
|
||||||
|
if ( std::find(callstack.begin(), callstack.end(), std::string(funcname)) != callstack.end() )
|
||||||
|
return "use";
|
||||||
|
callstack.push_back(funcname);
|
||||||
|
|
||||||
|
int par = 1;
|
||||||
|
int parlevel = 0;
|
||||||
|
for ( ; tok; tok = tok->next )
|
||||||
|
{
|
||||||
|
if ( Match(tok, "(") )
|
||||||
|
++parlevel;
|
||||||
|
else if ( Match(tok, ")") )
|
||||||
|
{
|
||||||
|
--parlevel;
|
||||||
|
if ( parlevel < 1 )
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( parlevel == 1 )
|
||||||
|
{
|
||||||
|
if ( Match(tok, ",") )
|
||||||
|
++par;
|
||||||
|
if ( Match(tok, "[,()] %var1% [,()]", varnames) )
|
||||||
|
{
|
||||||
|
const TOKEN *ftok = GetFunctionTokenByName(funcname);
|
||||||
|
const char *parname = GetParameterName( ftok, par );
|
||||||
|
if ( ! parname )
|
||||||
|
return "use";
|
||||||
|
// Check if the function deallocates the variable..
|
||||||
|
while ( ftok && ! Match(ftok,"{") )
|
||||||
|
ftok = ftok->next;
|
||||||
|
TOKEN *func = getcode( Tokenizer::gettok(ftok,1), parname );
|
||||||
|
const char *ret = 0;
|
||||||
|
if ( findmatch(func, "use") )
|
||||||
|
ret = "use";
|
||||||
|
if ( findmatch(func, "dealloc") )
|
||||||
|
ret = "dealloc";
|
||||||
|
deleteTokens(func);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
static void MismatchError( const TOKEN *Tok1, const char varname[] )
|
static void MismatchError( const TOKEN *Tok1, const char varname[] )
|
||||||
{
|
{
|
||||||
|
@ -374,9 +429,13 @@ static TOKEN *getcode(const TOKEN *tok, const char varname[])
|
||||||
if ( Match(tok,"[)=] %var1% [;)]", varnames) )
|
if ( Match(tok,"[)=] %var1% [;)]", varnames) )
|
||||||
addtoken("use");
|
addtoken("use");
|
||||||
|
|
||||||
// Function parameter..
|
// Investigate function calls..
|
||||||
if ( Match(tok, "[(,)] %var1% [,)]", varnames) )
|
if ( Match(tok, "%var% (") )
|
||||||
addtoken("use");
|
{
|
||||||
|
const char *str = call_func(tok, varnames);
|
||||||
|
if ( str )
|
||||||
|
addtoken( str );
|
||||||
|
}
|
||||||
|
|
||||||
// Linux lists..
|
// Linux lists..
|
||||||
if ( Match( tok, "[=(,] & %var1% [.[]", varnames ) )
|
if ( Match( tok, "[=(,] & %var1% [.[]", varnames ) )
|
||||||
|
@ -406,6 +465,8 @@ static void erase(TOKEN *begin, const TOKEN *end)
|
||||||
// Simpler but less powerful than "CheckMemoryLeak_CheckScope_All"
|
// Simpler but less powerful than "CheckMemoryLeak_CheckScope_All"
|
||||||
static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] )
|
static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] )
|
||||||
{
|
{
|
||||||
|
callstack.clear();
|
||||||
|
|
||||||
TOKEN *tok = getcode( Tok1, varname );
|
TOKEN *tok = getcode( Tok1, varname );
|
||||||
|
|
||||||
// If the variable is not allocated at all => no memory leak
|
// If the variable is not allocated at all => no memory leak
|
||||||
|
@ -415,7 +476,6 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[]
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Remove "do"...
|
// Remove "do"...
|
||||||
// do { x } while (y);
|
// do { x } while (y);
|
||||||
// =>
|
// =>
|
||||||
|
|
|
@ -232,7 +232,21 @@ const TOKEN *GetFunctionTokenByName( const char funcname[] )
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char *GetParameterName( const TOKEN *ftok, int par )
|
||||||
|
{
|
||||||
|
int _par = 1;
|
||||||
|
for ( ; ftok; ftok = ftok->next)
|
||||||
|
{
|
||||||
|
if ( Match(ftok, ",") )
|
||||||
|
++_par;
|
||||||
|
if ( par==_par && Match(ftok, "%var% [,)]") )
|
||||||
|
return ftok->str;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@ bool IsStandardType(const char str[]);
|
||||||
|
|
||||||
void FillFunctionList(const unsigned int file_id);
|
void FillFunctionList(const unsigned int file_id);
|
||||||
const TOKEN *GetFunctionTokenByName( const char funcname[] );
|
const TOKEN *GetFunctionTokenByName( const char funcname[] );
|
||||||
|
const char *GetParameterName( const TOKEN *ftok, int par );
|
||||||
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
|
||||||
|
|
||||||
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "CommonCheck.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "CheckMemoryLeak.h"
|
#include "CheckMemoryLeak.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
@ -49,6 +50,7 @@ private:
|
||||||
|
|
||||||
// Check for memory leaks..
|
// Check for memory leaks..
|
||||||
ShowAll = false;
|
ShowAll = false;
|
||||||
|
FillFunctionList(0);
|
||||||
CheckMemoryLeak();
|
CheckMemoryLeak();
|
||||||
|
|
||||||
tokenizer.DeallocateTokens();
|
tokenizer.DeallocateTokens();
|
||||||
|
@ -97,6 +99,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE( func1 );
|
TEST_CASE( func1 );
|
||||||
TEST_CASE( func2 );
|
TEST_CASE( func2 );
|
||||||
|
TEST_CASE( func3 );
|
||||||
|
|
||||||
TEST_CASE( class1 );
|
TEST_CASE( class1 );
|
||||||
TEST_CASE( class2 );
|
TEST_CASE( class2 );
|
||||||
|
@ -587,6 +590,20 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void func3()
|
||||||
|
{
|
||||||
|
check( "static void foo(const char *str)\n"
|
||||||
|
"{ }\n"
|
||||||
|
"\n"
|
||||||
|
"static void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" char *p = new char[100];\n"
|
||||||
|
" foo(p);\n"
|
||||||
|
"}\n" );
|
||||||
|
ASSERT_EQUALS( std::string("[test.cpp:8]: Memory leak: p\n"), errout.str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void func3()
|
void func3()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue