From c833b51b25d29d7734042d9ee17f4a6382f5bfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 15 Aug 2008 19:17:06 +0000 Subject: [PATCH] CheckMemoryLeak: Made the checking a lot simpler when "--all" is not given. This should give few false positives --- CheckMemoryLeak.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++-- tests.cpp | 60 ++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 29 deletions(-) diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index 1040e47f5..407023c1e 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -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]; varnames[0] = varname; @@ -151,7 +151,7 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] if ( indentlevel < 0 ) { if ( Alloc != No ) - MemoryLeak( Tok1, varname ); + MemoryLeak( tok, varname ); return; } @@ -360,7 +360,7 @@ static void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] { if ( Alloc != No && Alloc != dealloc ) { - MismatchError( Tok1, varname ); + MismatchError( tok, varname ); 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; + } +} +//--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- diff --git a/tests.cpp b/tests.cpp index a809aa7ca..d4e74615a 100644 --- a/tests.cpp +++ b/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() { // There are 2 sections: @@ -476,12 +487,11 @@ static void memleak_in_function() // Simple testcases //////////////////////////////////////////////// - code = "void f()\n" "{\n" " int *a = new int[10];\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" @@ -489,7 +499,7 @@ static void memleak_in_function() " Fred *f = new Fred;\n" " return f;\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "static char *f()\n" @@ -497,7 +507,7 @@ static void memleak_in_function() " char *s = new char[100];\n" " return (char *)s;\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "static void f()\n" @@ -506,9 +516,7 @@ static void memleak_in_function() " char *str2 = (char *)str;\n" " free(str2);\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); - - + check_( CheckMemoryLeak, __LINE__, code, "" ); @@ -525,7 +533,7 @@ static void memleak_in_function() " delete [] a;\n" " }\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "void f()\n" @@ -549,7 +557,7 @@ static void memleak_in_function() " return;\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" @@ -562,7 +570,7 @@ static void memleak_in_function() " }\n" " delete [] str;\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); @@ -581,7 +589,7 @@ static void memleak_in_function() " }\n" " delete fred;\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); */ code = "static char *f()\n" @@ -605,9 +613,9 @@ static void memleak_in_function() " }\n" " return s;\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); - + check_( CheckMemoryLeak, __LINE__, code, "" ); +/* todo code = "static char *f()\n" "{\n" " char *s = new char[10];\n" @@ -618,7 +626,7 @@ static void memleak_in_function() " return 0;\n" "}\n"; check( CheckMemoryLeak, __LINE__, code, "" ); - +*/ @@ -639,7 +647,7 @@ static void memleak_in_function() " }\n" " free(str);\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "void f()\n" @@ -674,7 +682,7 @@ static void memleak_in_function() " };\n" " delete [] str;\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" " free(a);\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 is deleted automaticly\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "struct abc\n" @@ -741,7 +749,7 @@ static void memleak_in_function() " char *str[10];\n" " str[0] = strdup(\"hello\");\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" " free( fred->Name );\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 @@ -770,7 +778,7 @@ static void memleak_in_function() " Fred f;\n" " f.str = strdup(\"aa\");\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" " char *p = dmalloc();\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" @@ -806,7 +814,7 @@ static void memleak_in_function() " char *p = dmalloc();\n" " delete p;\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" @@ -817,7 +825,7 @@ static void memleak_in_function() " char *p = new char[100];\n" " foo(p);\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" @@ -825,7 +833,7 @@ static void memleak_in_function() " char *p = new char[100];\n" " foo(p);\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); code = "static void f()\n" @@ -833,7 +841,7 @@ static void memleak_in_function() " char *p = new char[100];\n" " foo.add(p);\n" "}\n"; - check( CheckMemoryLeak, __LINE__, code, "" ); + check_( CheckMemoryLeak, __LINE__, code, "" ); } //---------------------------------------------------------------------------