CheckMemoryLeak: Made the checking a lot simpler when "--all" is not
given. This should give few false positives
This commit is contained in:
parent
fcbd297ff0
commit
c833b51b25
|
@ -124,7 +124,7 @@ static void MemoryLeak( const TOKEN *tok, const char varname[] )
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] )
|
static void CheckMemoryLeak_CheckScope_All( const TOKEN *Tok1, const char varname[] )
|
||||||
{
|
{
|
||||||
const char *varnames[2];
|
const char *varnames[2];
|
||||||
varnames[0] = varname;
|
varnames[0] = varname;
|
||||||
|
@ -151,7 +151,7 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[]
|
||||||
if ( indentlevel < 0 )
|
if ( indentlevel < 0 )
|
||||||
{
|
{
|
||||||
if ( Alloc != No )
|
if ( Alloc != No )
|
||||||
MemoryLeak( Tok1, varname );
|
MemoryLeak( tok, varname );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[]
|
||||||
{
|
{
|
||||||
if ( Alloc != No && Alloc != dealloc )
|
if ( Alloc != No && Alloc != dealloc )
|
||||||
{
|
{
|
||||||
MismatchError( Tok1, varname );
|
MismatchError( tok, varname );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,6 +478,85 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[]
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern bool ShowAll;
|
||||||
|
|
||||||
|
// Simpler but less powerful than "CheckMemoryLeak_CheckScope_All"
|
||||||
|
static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] )
|
||||||
|
{
|
||||||
|
if ( ShowAll )
|
||||||
|
{
|
||||||
|
CheckMemoryLeak_CheckScope_All(Tok1, varname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *varnames[2];
|
||||||
|
varnames[0] = varname;
|
||||||
|
varnames[1] = 0;
|
||||||
|
|
||||||
|
AllocType Alloc = No;
|
||||||
|
|
||||||
|
bool isfunc = false;
|
||||||
|
bool isreturn = false;
|
||||||
|
|
||||||
|
int indentlevel = 0;
|
||||||
|
for (const TOKEN *tok = Tok1 ; tok; tok = tok->next )
|
||||||
|
{
|
||||||
|
if (tok->str[0]=='{')
|
||||||
|
indentlevel++;
|
||||||
|
|
||||||
|
else if (tok->str[0]=='}')
|
||||||
|
{
|
||||||
|
indentlevel--;
|
||||||
|
if ( indentlevel < 0 )
|
||||||
|
{
|
||||||
|
if ( Alloc != No )
|
||||||
|
MemoryLeak( tok, varname );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocated..
|
||||||
|
if ( Alloc == No && Match(tok, "[(;{}] %var1% =", varnames) )
|
||||||
|
Alloc = GetAllocationType( gettok(tok, 3) );
|
||||||
|
|
||||||
|
// Deallocated..
|
||||||
|
AllocType dealloc = GetDeallocationType( tok, varnames );
|
||||||
|
if ( dealloc != No )
|
||||||
|
{
|
||||||
|
if ( Alloc != No && Alloc != dealloc )
|
||||||
|
MismatchError( tok, varname );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Match(tok,";") )
|
||||||
|
isfunc = isreturn = false;
|
||||||
|
|
||||||
|
// Assignment..
|
||||||
|
if ( Match(tok, "[=)&] %var1%", varnames) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Assuming that it's deallocated if it's passed as parameter to a
|
||||||
|
// function
|
||||||
|
if ( Match(tok, "%var% (") &&
|
||||||
|
strcmp(tok->str,"if") &&
|
||||||
|
strcmp(tok->str,"for") &&
|
||||||
|
strcmp(tok->str,"while"))
|
||||||
|
{
|
||||||
|
isfunc = true;
|
||||||
|
}
|
||||||
|
if (isfunc && Match(tok,"[(,] %var1% [,)]", varnames))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Return variable..
|
||||||
|
if (Match(tok, "return"))
|
||||||
|
isreturn = true;
|
||||||
|
if (isreturn && Match(tok,varname))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
60
tests.cpp
60
tests.cpp
|
@ -455,6 +455,17 @@ static void operator_eq()
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void check_(void (chk)(),
|
||||||
|
const unsigned int line,
|
||||||
|
const char code[],
|
||||||
|
const char msg[])
|
||||||
|
{
|
||||||
|
ShowAll = false;
|
||||||
|
check( chk, line, code, msg );
|
||||||
|
ShowAll = true;
|
||||||
|
check( chk, line, code, msg );
|
||||||
|
}
|
||||||
|
|
||||||
static void memleak_in_function()
|
static void memleak_in_function()
|
||||||
{
|
{
|
||||||
// There are 2 sections:
|
// There are 2 sections:
|
||||||
|
@ -476,12 +487,11 @@ static void memleak_in_function()
|
||||||
// Simple testcases
|
// Simple testcases
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
code = "void f()\n"
|
code = "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int *a = new int[10];\n"
|
" int *a = new int[10];\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: a\n" );
|
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:4]: Memory leak: a\n" );
|
||||||
|
|
||||||
|
|
||||||
code = "Fred *NewFred()\n"
|
code = "Fred *NewFred()\n"
|
||||||
|
@ -489,7 +499,7 @@ static void memleak_in_function()
|
||||||
" Fred *f = new Fred;\n"
|
" Fred *f = new Fred;\n"
|
||||||
" return f;\n"
|
" return f;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "static char *f()\n"
|
code = "static char *f()\n"
|
||||||
|
@ -497,7 +507,7 @@ static void memleak_in_function()
|
||||||
" char *s = new char[100];\n"
|
" char *s = new char[100];\n"
|
||||||
" return (char *)s;\n"
|
" return (char *)s;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "static void f()\n"
|
code = "static void f()\n"
|
||||||
|
@ -506,9 +516,7 @@ static void memleak_in_function()
|
||||||
" char *str2 = (char *)str;\n"
|
" char *str2 = (char *)str;\n"
|
||||||
" free(str2);\n"
|
" free(str2);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -525,7 +533,7 @@ static void memleak_in_function()
|
||||||
" delete [] a;\n"
|
" delete [] a;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "void f()\n"
|
code = "void f()\n"
|
||||||
|
@ -549,7 +557,7 @@ static void memleak_in_function()
|
||||||
" return;\n"
|
" return;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: str\n" );
|
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:9]: Memory leak: str\n" );
|
||||||
|
|
||||||
|
|
||||||
code = "void f()\n"
|
code = "void f()\n"
|
||||||
|
@ -562,7 +570,7 @@ static void memleak_in_function()
|
||||||
" }\n"
|
" }\n"
|
||||||
" delete [] str;\n"
|
" delete [] str;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -581,7 +589,7 @@ static void memleak_in_function()
|
||||||
" }\n"
|
" }\n"
|
||||||
" delete fred;\n"
|
" delete fred;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
code = "static char *f()\n"
|
code = "static char *f()\n"
|
||||||
|
@ -605,9 +613,9 @@ static void memleak_in_function()
|
||||||
" }\n"
|
" }\n"
|
||||||
" return s;\n"
|
" return s;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
|
/* todo
|
||||||
code = "static char *f()\n"
|
code = "static char *f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *s = new char[10];\n"
|
" char *s = new char[10];\n"
|
||||||
|
@ -618,7 +626,7 @@ static void memleak_in_function()
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -639,7 +647,7 @@ static void memleak_in_function()
|
||||||
" }\n"
|
" }\n"
|
||||||
" free(str);\n"
|
" free(str);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "void f()\n"
|
code = "void f()\n"
|
||||||
|
@ -674,7 +682,7 @@ static void memleak_in_function()
|
||||||
" };\n"
|
" };\n"
|
||||||
" delete [] str;\n"
|
" delete [] str;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -690,7 +698,7 @@ static void memleak_in_function()
|
||||||
" int *a = new int[10];\n"
|
" int *a = new int[10];\n"
|
||||||
" free(a);\n"
|
" free(a);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Mismatching allocation and deallocation: a\n" );
|
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:4]: Mismatching allocation and deallocation: a\n" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -708,7 +716,7 @@ static void memleak_in_function()
|
||||||
" Fred *fred = new Fred;\n"
|
" Fred *fred = new Fred;\n"
|
||||||
" // fred is deleted automaticly\n"
|
" // fred is deleted automaticly\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "struct abc\n"
|
code = "struct abc\n"
|
||||||
|
@ -741,7 +749,7 @@ static void memleak_in_function()
|
||||||
" char *str[10];\n"
|
" char *str[10];\n"
|
||||||
" str[0] = strdup(\"hello\");\n"
|
" str[0] = strdup(\"hello\");\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: str[0]\n" );
|
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: str[0]\n" );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -756,7 +764,7 @@ static void memleak_in_function()
|
||||||
" Fred *fred = new Fred;\n"
|
" Fred *fred = new Fred;\n"
|
||||||
" free( fred->Name );\n"
|
" free( fred->Name );\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: fred\n" );
|
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:5]: Memory leak: fred\n" );
|
||||||
|
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
|
@ -770,7 +778,7 @@ static void memleak_in_function()
|
||||||
" Fred f;\n"
|
" Fred f;\n"
|
||||||
" f.str = strdup(\"aa\");\n"
|
" f.str = strdup(\"aa\");\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:9]: Memory leak: f.str\n" );
|
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:9]: Memory leak: f.str\n" );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -793,7 +801,7 @@ static void memleak_in_function()
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *p = dmalloc();\n"
|
" char *p = dmalloc();\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:8]: Memory leak: p\n" );
|
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:9]: Memory leak: p\n" );
|
||||||
|
|
||||||
|
|
||||||
code = "static char *dmalloc()\n"
|
code = "static char *dmalloc()\n"
|
||||||
|
@ -806,7 +814,7 @@ static void memleak_in_function()
|
||||||
" char *p = dmalloc();\n"
|
" char *p = dmalloc();\n"
|
||||||
" delete p;\n"
|
" delete p;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:8]: Mismatching allocation and deallocation: p\n" );
|
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:9]: Mismatching allocation and deallocation: p\n" );
|
||||||
|
|
||||||
|
|
||||||
code = "static void foo(const char *str)\n"
|
code = "static void foo(const char *str)\n"
|
||||||
|
@ -817,7 +825,7 @@ static void memleak_in_function()
|
||||||
" char *p = new char[100];\n"
|
" char *p = new char[100];\n"
|
||||||
" foo(p);\n"
|
" foo(p);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:6]: Memory leak: p\n" );
|
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:8]: Memory leak: p\n" );
|
||||||
|
|
||||||
|
|
||||||
code = "static void f()\n"
|
code = "static void f()\n"
|
||||||
|
@ -825,7 +833,7 @@ static void memleak_in_function()
|
||||||
" char *p = new char[100];\n"
|
" char *p = new char[100];\n"
|
||||||
" foo(p);\n"
|
" foo(p);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
|
|
||||||
code = "static void f()\n"
|
code = "static void f()\n"
|
||||||
|
@ -833,7 +841,7 @@ static void memleak_in_function()
|
||||||
" char *p = new char[100];\n"
|
" char *p = new char[100];\n"
|
||||||
" foo.add(p);\n"
|
" foo.add(p);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
check_( CheckMemoryLeak, __LINE__, code, "" );
|
||||||
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue