Fixed #264 (Memory Leak: alloc by assigning to a return value)
The fix was inspired by the previous patch submitted by hoangtuansu
This commit is contained in:
parent
195880807e
commit
433ff048a4
|
@ -252,7 +252,37 @@ void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &calls
|
||||||
error(callstack, "error", "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname);
|
error(callstack, "error", "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const
|
||||||
|
{
|
||||||
|
// Locate the start of the function..
|
||||||
|
unsigned int parlevel = 0;
|
||||||
|
while (tok)
|
||||||
|
{
|
||||||
|
if (tok->str() == "{" || tok->str() == "}")
|
||||||
|
return No;
|
||||||
|
|
||||||
|
if (tok->str() == "(")
|
||||||
|
{
|
||||||
|
if (parlevel != 0)
|
||||||
|
return No;
|
||||||
|
++parlevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (tok->str() == ")")
|
||||||
|
{
|
||||||
|
if (parlevel != 1)
|
||||||
|
return No;
|
||||||
|
if (Token::Match(tok, ") const| { return new %type% ; }"))
|
||||||
|
return New;
|
||||||
|
if (Token::Match(tok, ") const| { return new %type% [ %any% ] ; }"))
|
||||||
|
return NewArray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = tok->next();
|
||||||
|
}
|
||||||
|
return No;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,6 +385,14 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
|
||||||
}
|
}
|
||||||
callstack.push_back(tok);
|
callstack.push_back(tok);
|
||||||
|
|
||||||
|
// Check if this is a function that allocates memory..
|
||||||
|
{
|
||||||
|
const Token *ftok = _tokenizer->GetFunctionTokenByName(funcname.c_str());
|
||||||
|
AllocType a = functionReturnType(ftok);
|
||||||
|
if (a != No)
|
||||||
|
return "alloc";
|
||||||
|
}
|
||||||
|
|
||||||
// how many parameters is there in the function call?
|
// how many parameters is there in the function call?
|
||||||
int numpar = countParameters(tok);
|
int numpar = countParameters(tok);
|
||||||
if (numpar <= 0)
|
if (numpar <= 0)
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Token;
|
||||||
|
|
||||||
class CheckMemoryLeak
|
class CheckMemoryLeak
|
||||||
{
|
{
|
||||||
protected:
|
public:
|
||||||
CheckMemoryLeak() { }
|
CheckMemoryLeak() { }
|
||||||
|
|
||||||
/** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */
|
/** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */
|
||||||
|
@ -68,6 +68,9 @@ protected:
|
||||||
// error message
|
// error message
|
||||||
virtual void error(const Token *tok, const std::string &severity, const std::string &id, const std::string &msg) = 0;
|
virtual void error(const Token *tok, const std::string &severity, const std::string &id, const std::string &msg) = 0;
|
||||||
virtual void error(const std::list<const Token *> &callstack, const std::string &severity, const std::string &id, const std::string &msg) = 0;
|
virtual void error(const std::list<const Token *> &callstack, const std::string &severity, const std::string &id, const std::string &msg) = 0;
|
||||||
|
|
||||||
|
/** What type of allocated memory does the given function return? */
|
||||||
|
AllocType functionReturnType(const Token *tok) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,61 @@
|
||||||
#include "../src/checkmemoryleak.h"
|
#include "../src/checkmemoryleak.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
|
|
||||||
|
class TestMemleak : private TestFixture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestMemleak() : TestFixture("TestMemleak")
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
TEST_CASE(testFunctionReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckMemoryLeak::AllocType functionReturnType(const char code[])
|
||||||
|
{
|
||||||
|
// Tokenize..
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
|
||||||
|
return ((const CheckMemoryLeak *)0)->functionReturnType(tokenizer.tokens());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFunctionReturnType()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const char code[] = "const char *foo()\n"
|
||||||
|
"{ return 0; }";
|
||||||
|
ASSERT_EQUALS(CheckMemoryLeak::No, functionReturnType(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "Fred *newFred()\n"
|
||||||
|
"{ return new Fred; }";
|
||||||
|
ASSERT_EQUALS(CheckMemoryLeak::New, functionReturnType(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "char *foo()\n"
|
||||||
|
"{ return new char[100]; }";
|
||||||
|
ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TestMemleak testMemleak;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestMemleakInFunction : public TestFixture
|
class TestMemleakInFunction : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -145,6 +195,8 @@ private:
|
||||||
TEST_CASE(func13);
|
TEST_CASE(func13);
|
||||||
TEST_CASE(func14);
|
TEST_CASE(func14);
|
||||||
|
|
||||||
|
TEST_CASE(allocfunc1);
|
||||||
|
|
||||||
TEST_CASE(throw1);
|
TEST_CASE(throw1);
|
||||||
TEST_CASE(throw2);
|
TEST_CASE(throw2);
|
||||||
|
|
||||||
|
@ -1366,38 +1418,20 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
void allocfunc1()
|
||||||
void func3()
|
{
|
||||||
{
|
check("static char *a()\n"
|
||||||
check( "static char *dmalloc()\n"
|
"{\n"
|
||||||
"{\n"
|
" return new char[100];\n"
|
||||||
" char *p = new char[100];\n"
|
"}\n"
|
||||||
" return p;\n"
|
"static void b()\n"
|
||||||
"}\n"
|
"{\n"
|
||||||
"static void f()\n"
|
" char *p = a();\n"
|
||||||
"{\n"
|
"}\n");
|
||||||
" char *p = dmalloc();\n"
|
ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Memory leak: p\n"), errout.str());
|
||||||
"}\n" );
|
}
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:9]: Memory leak: p\n"), errout.str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void func4()
|
|
||||||
{
|
|
||||||
check( "static char *dmalloc()\n"
|
|
||||||
"{\n"
|
|
||||||
" char *p = new char[100];\n"
|
|
||||||
" return p;\n"
|
|
||||||
"}\n"
|
|
||||||
"static void f()\n"
|
|
||||||
"{\n"
|
|
||||||
" char *p = dmalloc();\n"
|
|
||||||
" delete p;\n"
|
|
||||||
"}\n" );
|
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:9]: Mismatching allocation and deallocation: p\n"), errout.str() );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue