CheckMemoryLeak: Detect memory leaks for class members

This commit is contained in:
Daniel Marjamäki 2007-06-10 18:25:39 +00:00
parent 8a1ec67b22
commit 6ed70ae745
3 changed files with 215 additions and 3 deletions

View File

@ -1,6 +1,7 @@
#include "CheckMemoryLeak.h"
#include "Tokenize.h"
#include "Statements.h"
#include "CommonCheck.h"
@ -23,12 +24,11 @@ struct _variable
//---------------------------------------------------------------------------
// Checks for memory leaks..
// Checks for memory leaks inside function..
//---------------------------------------------------------------------------
void CheckMemoryLeak()
static void _InFunction()
{
std::vector<_variable *> varlist;
@ -290,4 +290,192 @@ void CheckMemoryLeak()
//---------------------------------------------------------------------------
// Check that all class members are deallocated..
//---------------------------------------------------------------------------
static void _ClassMembers_CheckVar(const char *classname, const char *varname)
{
// Check how the variable 'varname' is allocated..
enum {No, New, NewA, Malloc} Alloc, Dealloc;
Alloc = Dealloc = No;
for (TOKEN *func = tokens; func; func = func->next)
{
if (strcmp(func->str, classname))
continue;
if (strcmp(getstr(func, 1), "::") != 0)
continue;
if (strcmp(getstr(func, 3), "(") != 0)
continue;
int indentlevel = 0;
for (TOKEN *tok = func; tok; tok = tok->next)
{
if (tok->str[0] == '{')
{
indentlevel++;
}
else if (tok->str[0] == '}')
{
indentlevel--;
if (indentlevel == 0)
{
func = tok;
break;
}
}
else if (indentlevel > 0)
{
// Deallocation..
if (strcmp(tok->str,"delete")==0 || strcmp(tok->str,"free")==0)
{
bool err = false;
if (match(tok, "delete var ;") &&
strcmp(getstr(tok,1),varname)==0)
{
err |= ( Dealloc != No && Dealloc != New );
Dealloc = New;
}
else if (match(tok, "delete [ ] var ;") &&
strcmp(getstr(tok,3),varname)==0)
{
err |= ( Dealloc != No && Dealloc != NewA );
Dealloc = NewA;
}
else if (match(tok, "free ( var )") &&
strcmp(getstr(tok,2),varname)==0)
{
err |= ( Dealloc != No && Dealloc != Malloc );
Dealloc = Malloc;
}
if (err)
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Mismatching deallocation for '" << classname << "::" << varname << "'";
ReportErr(ostr.str());
}
}
else
{
// Allocation...
if ( strcmp(tok->str, varname) != 0 )
continue;
if ( strcmp(getstr(tok,1), "=") != 0 )
continue;
bool err = false;
if ( strcmp(getstr(tok,2), "new") == 0 )
{
if ( match(tok, "var = new type ;") ||
match(tok, "var = new type (") )
{
err |= ( Alloc != No && Alloc != New );
Alloc = New;
}
else if ( match(tok, "var = new type [") )
{
err |= ( Alloc != No && Alloc != NewA );
Alloc = NewA;
}
}
else if ( match(tok, "var = strdup (") ||
match(tok, "var = ( type * ) malloc ("))
{
err |= ( Alloc != No && Alloc != Malloc );
Alloc = Malloc;
}
if (err)
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Mismatching allocation for '" << classname << "::" << varname << "'";
ReportErr(ostr.str());
}
}
}
}
}
if ( Alloc != Dealloc )
{
if ( Dealloc == No )
{
std::ostringstream ostr;
ostr << "Memory leak for '" << classname << "::" << varname << "'";
ReportErr(ostr.str());
}
}
}
static void _ClassMembers()
{
for (TOKEN *ClassDecl = tokens; ClassDecl; ClassDecl = ClassDecl->next)
{
// Is this a class declaration?
// -------------------------------------
if ( ! match(ClassDecl, "class var {") )
continue;
const char *classname = getstr(ClassDecl, 1);
// Locate member variables..
int indentlevel = 0;
for (TOKEN *ClassVar = ClassDecl; ClassVar; ClassVar = ClassVar->next)
{
if ( ClassVar->str[0] == '{' )
indentlevel++;
else if ( ClassVar->str[0] == '}' )
{
indentlevel--;
if (indentlevel == 0)
break;
}
else if (indentlevel == 1)
{
if ( match(ClassVar, "type * var ;") )
{
const char *varname = getstr(ClassVar, 2);
// Check the variable usage..
_ClassMembers_CheckVar(classname, varname);
}
}
}
}
}
//---------------------------------------------------------------------------
// Checks for memory leaks..
//---------------------------------------------------------------------------
void CheckMemoryLeak()
{
// Check for memory leaks inside functions..
_InFunction();
// Check that all class members are deallocated..
_ClassMembers();
}
//---------------------------------------------------------------------------

1
testmemleak1/err.msg Normal file
View File

@ -0,0 +1 @@
Memory leak for 'clKalle::str'

View File

@ -0,0 +1,23 @@
class clKalle
{
private:
char *str;
char *str2;
public:
clKalle();
~clKalle();
};
clKalle::clKalle()
{
str = new char[10];
str2 = new char[10];
}
clKalle::~clKalle()
{
delete [] str2;
}