2008-12-18 22:28:57 +01:00
|
|
|
/*
|
2009-01-21 21:04:20 +01:00
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2015-01-03 12:14:58 +01:00
|
|
|
* Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team.
|
2008-12-18 22:28:57 +01:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2009-09-27 17:08:31 +02:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2008-12-18 22:28:57 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
2009-06-08 18:51:17 +02:00
|
|
|
#ifndef checkmemoryleakH
|
|
|
|
#define checkmemoryleakH
|
2008-12-18 22:28:57 +01:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2009-06-08 20:54:49 +02:00
|
|
|
/**
|
2010-03-13 22:16:06 +01:00
|
|
|
* @file
|
|
|
|
*
|
|
|
|
* %Check for memory leaks
|
2009-06-08 20:54:49 +02:00
|
|
|
*
|
2011-09-08 18:23:25 +02:00
|
|
|
* The checking is split up into three specialized classes.
|
2009-07-17 10:49:01 +02:00
|
|
|
* - CheckMemoryLeakInFunction can detect when a function variable is allocated but not deallocated properly.
|
|
|
|
* - CheckMemoryLeakInClass can detect when a class variable is allocated but not deallocated properly.
|
2010-03-13 21:12:18 +01:00
|
|
|
* - CheckMemoryLeakStructMember checks allocation/deallocation of structs and struct members
|
2009-06-08 20:54:49 +02:00
|
|
|
*/
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
#include "config.h"
|
2009-03-20 18:16:21 +01:00
|
|
|
#include "check.h"
|
|
|
|
|
2008-12-18 22:28:57 +01:00
|
|
|
#include <list>
|
2009-03-20 18:16:21 +01:00
|
|
|
#include <string>
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2011-12-23 22:31:48 +01:00
|
|
|
class Scope;
|
2012-05-03 10:43:47 +02:00
|
|
|
class Function;
|
|
|
|
class Variable;
|
2009-03-20 18:16:21 +01:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/// @addtogroup Core
|
|
|
|
/// @{
|
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/** @brief Base class for memory leaks checking */
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckMemoryLeak {
|
2015-01-30 20:55:53 +01:00
|
|
|
protected:
|
2010-03-13 21:12:18 +01:00
|
|
|
/** For access to the tokens */
|
2009-07-13 15:07:26 +02:00
|
|
|
const Tokenizer * const tokenizer;
|
2010-03-13 21:12:18 +01:00
|
|
|
|
2015-01-30 20:55:53 +01:00
|
|
|
private:
|
2010-03-13 21:12:18 +01:00
|
|
|
/** ErrorLogger used to report errors */
|
2009-07-13 15:07:26 +02:00
|
|
|
ErrorLogger * const errorLogger;
|
|
|
|
|
2012-03-18 07:49:22 +01:00
|
|
|
/** Enabled standards */
|
2013-07-05 20:55:31 +02:00
|
|
|
const Settings * const settings1;
|
2012-03-18 07:49:22 +01:00
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/** Disable the default constructors */
|
|
|
|
CheckMemoryLeak();
|
|
|
|
|
|
|
|
/** Disable the default constructors */
|
|
|
|
CheckMemoryLeak(const CheckMemoryLeak &);
|
|
|
|
|
2009-09-13 09:03:48 +02:00
|
|
|
/** disable assignment operator */
|
|
|
|
void operator=(const CheckMemoryLeak &);
|
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/**
|
|
|
|
* Report error. Similar with the function Check::reportError
|
|
|
|
* @param location the token where the error occurs
|
|
|
|
* @param severity the severity of the bug
|
|
|
|
* @param id type of message
|
|
|
|
* @param msg text
|
|
|
|
*/
|
2010-07-14 16:30:03 +02:00
|
|
|
void reportErr(const Token *location, Severity::SeverityType severity, const std::string &id, const std::string &msg) const;
|
2009-07-17 10:49:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Report error. Similar with the function Check::reportError
|
|
|
|
* @param callstack callstack of error
|
|
|
|
* @param severity the severity of the bug
|
|
|
|
* @param id type of message
|
|
|
|
* @param msg text
|
|
|
|
*/
|
2010-07-14 16:30:03 +02:00
|
|
|
void reportErr(const std::list<const Token *> &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg) const;
|
2009-07-13 15:07:26 +02:00
|
|
|
|
2009-06-15 17:44:59 +02:00
|
|
|
public:
|
2013-07-05 20:55:31 +02:00
|
|
|
CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s)
|
2014-11-20 14:20:09 +01:00
|
|
|
: tokenizer(t), errorLogger(e), settings1(s) {
|
2009-07-13 15:07:26 +02:00
|
|
|
}
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */
|
2014-01-26 17:02:36 +01:00
|
|
|
enum AllocType { No, Malloc, New, NewArray, File, Fd, Pipe, OtherMem, OtherRes, Many };
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2011-11-30 19:43:02 +01:00
|
|
|
void memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype);
|
2009-07-19 16:51:31 +02:00
|
|
|
|
|
|
|
/**
|
2010-03-13 21:12:18 +01:00
|
|
|
* @brief Get type of deallocation at given position
|
2009-08-19 19:42:07 +02:00
|
|
|
* @param tok position
|
2010-12-07 07:07:36 +01:00
|
|
|
* @param varname variable name
|
2009-08-19 19:42:07 +02:00
|
|
|
* @return type of deallocation
|
2009-07-19 16:51:31 +02:00
|
|
|
*/
|
2010-12-07 07:07:36 +01:00
|
|
|
AllocType getDeallocationType(const Token *tok, const std::string &varname) const;
|
2009-08-19 19:42:07 +02:00
|
|
|
|
|
|
|
/**
|
2010-03-13 21:12:18 +01:00
|
|
|
* @brief Get type of deallocation at given position
|
2009-08-19 19:42:07 +02:00
|
|
|
* @param tok position
|
2009-10-15 18:52:29 +02:00
|
|
|
* @param varid variable id
|
2009-08-19 19:42:07 +02:00
|
|
|
* @return type of deallocation
|
|
|
|
*/
|
2009-08-25 21:25:27 +02:00
|
|
|
AllocType getDeallocationType(const Token *tok, unsigned int varid) const;
|
2009-07-19 16:51:31 +02:00
|
|
|
|
|
|
|
/**
|
2010-03-13 21:12:18 +01:00
|
|
|
* @brief Get type of allocation at given position
|
2009-07-19 16:51:31 +02:00
|
|
|
*/
|
2012-09-11 18:03:47 +02:00
|
|
|
AllocType getAllocationType(const Token *tok2, unsigned int varid, std::list<const Function*> *callstack = NULL) const;
|
2009-07-19 16:51:31 +02:00
|
|
|
|
|
|
|
/**
|
2010-03-13 21:12:18 +01:00
|
|
|
* @brief Get type of reallocation at given position
|
2009-07-19 16:51:31 +02:00
|
|
|
*/
|
2013-07-30 12:52:27 +02:00
|
|
|
static AllocType getReallocationType(const Token *tok2, unsigned int varid);
|
2009-07-19 16:51:31 +02:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/**
|
|
|
|
* @brief Is a typename the name of a class?
|
2011-09-08 18:23:25 +02:00
|
|
|
* @param tok type token
|
|
|
|
* @param varid variable id
|
2010-03-13 21:12:18 +01:00
|
|
|
* @return true if the type name is the name of a class
|
|
|
|
*/
|
2012-09-11 19:19:11 +02:00
|
|
|
bool isclass(const Token *tok, unsigned int varid) const;
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2011-09-08 18:23:25 +02:00
|
|
|
/**
|
|
|
|
* Report that there is a memory leak (new/malloc/etc)
|
|
|
|
* @param tok token where memory is leaked
|
|
|
|
* @param varname name of variable
|
|
|
|
*/
|
2011-12-13 00:24:34 +01:00
|
|
|
void memleakError(const Token *tok, const std::string &varname) const;
|
2011-09-08 18:23:25 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Report that there is a resource leak (fopen/popen/etc)
|
|
|
|
* @param tok token where resource is leaked
|
|
|
|
* @param varname name of variable
|
|
|
|
*/
|
2012-05-17 10:33:24 +02:00
|
|
|
void resourceLeakError(const Token *tok, const std::string &varname) const;
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/**
|
|
|
|
* @brief Report error: deallocating a deallocated pointer
|
|
|
|
* @param tok token where error occurs
|
|
|
|
* @param varname name of variable
|
|
|
|
*/
|
2011-12-13 00:24:34 +01:00
|
|
|
void deallocDeallocError(const Token *tok, const std::string &varname) const;
|
|
|
|
void deallocuseError(const Token *tok, const std::string &varname) const;
|
|
|
|
void mismatchSizeError(const Token *tok, const std::string &sz) const;
|
|
|
|
void mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname) const;
|
|
|
|
void memleakUponReallocFailureError(const Token *tok, const std::string &varname) const;
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2009-06-15 17:44:59 +02:00
|
|
|
/** What type of allocated memory does the given function return? */
|
2012-09-11 18:03:47 +02:00
|
|
|
AllocType functionReturnType(const Function* func, std::list<const Function*> *callstack = NULL) const;
|
2010-06-05 01:58:50 +02:00
|
|
|
|
|
|
|
/** Function allocates pointed-to argument (a la asprintf)? */
|
2012-05-03 10:43:47 +02:00
|
|
|
const char *functionArgAlloc(const Function *func, unsigned int targetpar, AllocType &allocType) const;
|
2009-06-08 20:20:43 +02:00
|
|
|
};
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/// @}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @addtogroup Checks
|
|
|
|
/// @{
|
2009-06-08 20:20:43 +02:00
|
|
|
|
|
|
|
|
2009-06-08 20:54:49 +02:00
|
|
|
/**
|
2010-03-13 22:16:06 +01:00
|
|
|
* @brief %CheckMemoryLeakInFunction detects when a function variable is allocated but not deallocated properly.
|
2009-06-08 20:54:49 +02:00
|
|
|
*
|
|
|
|
* The checking is done by looking at each function variable separately. By repeating these 4 steps over and over:
|
2009-07-17 10:49:01 +02:00
|
|
|
* -# locate a function variable
|
|
|
|
* -# create a simple token list that describes the usage of the function variable.
|
|
|
|
* -# simplify the token list.
|
|
|
|
* -# finally, check if the simplified token list contain any leaks.
|
2009-06-08 20:54:49 +02:00
|
|
|
*/
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak {
|
2008-12-18 22:28:57 +01:00
|
|
|
public:
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief This constructor is used when registering this class */
|
2014-11-20 14:20:09 +01:00
|
|
|
CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(0, 0, 0), symbolDatabase(NULL) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-03-20 18:16:21 +01:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief This constructor is used when running checks */
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
2014-11-20 14:20:09 +01:00
|
|
|
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog, settings) {
|
2010-12-08 07:49:01 +01:00
|
|
|
// get the symbol database
|
2010-12-29 12:43:29 +01:00
|
|
|
if (tokenizr)
|
|
|
|
symbolDatabase = tokenizr->getSymbolDatabase();
|
|
|
|
else
|
|
|
|
symbolDatabase = 0;
|
2010-12-08 07:49:01 +01:00
|
|
|
}
|
2009-03-20 18:16:21 +01:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief run all simplified checks */
|
2014-11-20 14:20:09 +01:00
|
|
|
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) {
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakInFunction checkMemoryLeak(tokenizr, settings, errLog);
|
2010-05-18 07:46:48 +02:00
|
|
|
checkMemoryLeak.checkReallocUsage();
|
2009-06-08 20:20:43 +02:00
|
|
|
checkMemoryLeak.check();
|
2009-03-20 18:16:21 +01:00
|
|
|
}
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief Unit testing : testing the white list */
|
2015-01-30 20:55:53 +01:00
|
|
|
static bool test_white_list(const std::string &funcname, const Settings *settings, bool cpp);
|
2010-01-18 21:34:11 +01:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** @brief Perform checking */
|
2009-06-08 20:20:43 +02:00
|
|
|
void check();
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2010-05-18 07:46:48 +02:00
|
|
|
/**
|
|
|
|
* Checking for a memory leak caused by improper realloc usage.
|
|
|
|
*/
|
|
|
|
void checkReallocUsage();
|
|
|
|
|
2008-12-18 22:28:57 +01:00
|
|
|
/**
|
2010-03-13 22:16:06 +01:00
|
|
|
* @brief %Check if there is a "!var" match inside a condition
|
2009-06-08 20:20:43 +02:00
|
|
|
* @param tok first token to match
|
2013-02-10 07:43:09 +01:00
|
|
|
* @param varid variable id
|
2009-06-08 20:20:43 +02:00
|
|
|
* @param endpar if this is true the "!var" must be followed by ")"
|
|
|
|
* @return true if match
|
2008-12-18 22:28:57 +01:00
|
|
|
*/
|
2012-09-11 19:19:11 +02:00
|
|
|
static bool notvar(const Token *tok, unsigned int varid, bool endpar = false);
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/**
|
|
|
|
* Inspect a function call. the call_func and getcode are recursive
|
|
|
|
* @param tok token where the function call occurs
|
|
|
|
* @param callstack callstack
|
2009-10-15 18:52:29 +02:00
|
|
|
* @param varid variable id to check
|
2009-07-17 10:49:01 +02:00
|
|
|
* @param alloctype if memory is allocated, this indicates the type of allocation
|
|
|
|
* @param dealloctype if memory is deallocated, this indicates the type of deallocation
|
2010-06-05 01:58:50 +02:00
|
|
|
* @param allocpar if function allocates varid parameter
|
2009-07-17 10:49:01 +02:00
|
|
|
* @param sz not used by call_func - see getcode
|
|
|
|
* @return These are the possible return values:
|
|
|
|
* - NULL : no significant code
|
|
|
|
* - "recursive" : recursive function
|
|
|
|
* - "alloc" : the function returns allocated memory
|
|
|
|
* - "dealloc" : the function deallocates the variable
|
|
|
|
* - "dealloc_"
|
|
|
|
* - "use" : the variable is used (unknown usage of the variable => the checking bails out)
|
2010-03-13 21:12:18 +01:00
|
|
|
* - "callfunc" : a function call with unknown side effects
|
2009-07-17 10:49:01 +02:00
|
|
|
* - "&use"
|
|
|
|
*/
|
2010-06-05 01:58:50 +02:00
|
|
|
const char * call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &allocpar, unsigned int sz);
|
2008-12-18 22:28:57 +01:00
|
|
|
|
|
|
|
/**
|
2009-07-17 10:49:01 +02:00
|
|
|
* Extract a new tokens list that is easier to parse than the "_tokenizer->tokens()", the
|
|
|
|
* extracted tokens list describes how the given variable is used.
|
|
|
|
* The getcode and call_func are recursive
|
2008-12-18 22:28:57 +01:00
|
|
|
* @param tok start parse token
|
|
|
|
* @param callstack callstack
|
2009-10-15 18:52:29 +02:00
|
|
|
* @param varid variable id
|
2009-07-17 10:49:01 +02:00
|
|
|
* @param alloctype keep track of what type of allocation is used
|
|
|
|
* @param dealloctype keeps track of what type of deallocation is used
|
|
|
|
* @param classmember should be set if the inspected function is a class member
|
|
|
|
* @param sz size of type, used to check for mismatching size of allocation. for example "int *a;" => the sz is "sizeof(int)"
|
2008-12-18 22:28:57 +01:00
|
|
|
* @return Newly allocated token array. Caller needs to release reserved
|
2012-05-05 18:33:26 +02:00
|
|
|
* memory by calling TokenList::deleteTokens(returnValue);
|
2009-07-17 10:49:01 +02:00
|
|
|
* Returned tokens:
|
2011-09-08 18:28:05 +02:00
|
|
|
* - "alloc" : the variable is allocated
|
|
|
|
* - "assign" : the variable is assigned a new value
|
|
|
|
* - "break" : corresponds to "break"
|
|
|
|
* - "callfunc" : a function call with unknown side effects
|
|
|
|
* - "continue" : corresponds to "continue"
|
|
|
|
* - "dealloc" : the variable is deallocated
|
|
|
|
* - "goto" : corresponds to a "goto"
|
|
|
|
* - "if" : there is an "if"
|
|
|
|
* - "if(var)" : corresponds with "if ( var != 0 )"
|
|
|
|
* - "if(!var)" : corresponds with "if ( var == 0 )"
|
|
|
|
* - "ifv" : the variable is used in some way in a "if"
|
|
|
|
* - "loop" : corresponds to either a "for" or a "while"
|
|
|
|
* - "realloc" : the variable is reallocated
|
|
|
|
* - "return" : corresponds to a "return"
|
|
|
|
* - "use" : unknown usage -> bail out checking of this execution path
|
|
|
|
* - "&use" : the address of the variable is taken
|
|
|
|
* - "::use" : calling member function of class
|
2012-12-09 08:59:21 +01:00
|
|
|
* - "use_" : content of variable is accessed (used to warn access after dealloc)
|
2008-12-18 22:28:57 +01:00
|
|
|
*/
|
2010-05-16 19:55:16 +02:00
|
|
|
Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, unsigned int sz);
|
2009-02-04 07:11:36 +01:00
|
|
|
|
|
|
|
/**
|
2009-06-08 20:20:43 +02:00
|
|
|
* Simplify code e.g. by replacing empty "{ }" with ";"
|
|
|
|
* @param tok first token. The tokens list can be modified.
|
2009-02-04 07:11:36 +01:00
|
|
|
*/
|
2012-05-17 10:33:24 +02:00
|
|
|
void simplifycode(Token *tok) const;
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2010-05-16 19:55:16 +02:00
|
|
|
static const Token *findleak(const Token *tokens);
|
2009-08-23 15:48:25 +02:00
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/**
|
|
|
|
* Checking the variable varname
|
|
|
|
* @param Tok1 start token
|
2009-10-15 18:52:29 +02:00
|
|
|
* @param varname name of variable (for error messages)
|
|
|
|
* @param varid variable id
|
2009-07-17 10:49:01 +02:00
|
|
|
* @param classmember is the scope inside a class member function
|
|
|
|
* @param sz size of type.. if the variable is a "int *" then sz should be "sizeof(int)"
|
|
|
|
*/
|
2009-09-10 21:22:57 +02:00
|
|
|
void checkScope(const Token *Tok1, const std::string &varname, unsigned int varid, bool classmember, unsigned int sz);
|
2008-12-20 18:52:15 +01:00
|
|
|
|
2012-03-16 19:52:18 +01:00
|
|
|
private:
|
2010-03-13 21:12:18 +01:00
|
|
|
/** Report all possible errors (for the --errorlist) */
|
2014-11-20 14:20:09 +01:00
|
|
|
void getErrorMessages(ErrorLogger *e, const Settings *settings) const {
|
2010-12-29 12:43:29 +01:00
|
|
|
CheckMemoryLeakInFunction c(0, settings, e);
|
2009-08-04 21:36:55 +02:00
|
|
|
|
2011-11-30 19:43:02 +01:00
|
|
|
c.memleakError(0, "varname");
|
|
|
|
c.resourceLeakError(0, "varname");
|
2010-12-29 12:43:29 +01:00
|
|
|
|
|
|
|
c.deallocDeallocError(0, "varname");
|
|
|
|
c.deallocuseError(0, "varname");
|
|
|
|
c.mismatchSizeError(0, "sz");
|
2009-08-04 21:36:55 +02:00
|
|
|
std::list<const Token *> callstack;
|
2010-12-29 12:43:29 +01:00
|
|
|
c.mismatchAllocDealloc(callstack, "varname");
|
|
|
|
c.memleakUponReallocFailureError(0, "varname");
|
2009-08-04 21:36:55 +02:00
|
|
|
}
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/**
|
|
|
|
* Get name of class (--doc)
|
|
|
|
* @return name of class
|
|
|
|
*/
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2009-06-12 15:20:08 +02:00
|
|
|
return "Memory leaks (function variables)";
|
|
|
|
}
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/**
|
|
|
|
* Get class information (--doc)
|
|
|
|
* @return Wiki formatted information about this class
|
|
|
|
*/
|
2014-11-20 14:20:09 +01:00
|
|
|
std::string classInfo() const {
|
2012-08-26 16:22:46 +02:00
|
|
|
return "Is there any allocated memory when a function goes out of scope\n";
|
2009-06-12 12:19:37 +02:00
|
|
|
}
|
2009-11-14 09:06:28 +01:00
|
|
|
|
2011-01-16 18:13:54 +01:00
|
|
|
const SymbolDatabase *symbolDatabase;
|
2009-06-08 20:20:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-06-08 20:54:49 +02:00
|
|
|
/**
|
2009-07-17 10:49:01 +02:00
|
|
|
* @brief %Check class variables, variables that are allocated in the constructor should be deallocated in the destructor
|
2009-06-08 20:54:49 +02:00
|
|
|
*/
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckMemoryLeakInClass : private Check, private CheckMemoryLeak {
|
2009-06-08 20:20:43 +02:00
|
|
|
public:
|
2014-11-20 14:20:09 +01:00
|
|
|
CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(0, 0, 0) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakInClass(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
2014-11-20 14:20:09 +01:00
|
|
|
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog, settings) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) {
|
2012-09-10 19:02:32 +02:00
|
|
|
if (!tokenizr->isCPP())
|
2010-10-19 21:54:15 +02:00
|
|
|
return;
|
|
|
|
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakInClass checkMemoryLeak(tokenizr, settings, errLog);
|
2009-06-08 20:20:43 +02:00
|
|
|
checkMemoryLeak.check();
|
|
|
|
}
|
|
|
|
|
|
|
|
void check();
|
|
|
|
|
|
|
|
private:
|
2011-01-17 18:29:19 +01:00
|
|
|
void variable(const Scope *scope, const Token *tokVarname);
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2010-05-15 19:40:32 +02:00
|
|
|
/** Public functions: possible double-allocation */
|
2011-01-17 18:29:19 +01:00
|
|
|
void checkPublicFunctions(const Scope *scope, const Token *classtok);
|
2010-05-15 19:40:32 +02:00
|
|
|
void publicAllocationError(const Token *tok, const std::string &varname);
|
|
|
|
|
2012-09-10 17:27:41 +02:00
|
|
|
void unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname);
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void getErrorMessages(ErrorLogger *e, const Settings *settings) const {
|
2012-09-10 17:27:41 +02:00
|
|
|
CheckMemoryLeakInClass c(0, settings, e);
|
|
|
|
c.publicAllocationError(0, "varname");
|
|
|
|
c.unsafeClassError(0, "class", "class::varname");
|
|
|
|
}
|
2009-03-22 08:20:15 +01:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2009-06-12 15:20:08 +02:00
|
|
|
return "Memory leaks (class variables)";
|
|
|
|
}
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
std::string classInfo() const {
|
2012-08-26 16:22:46 +02:00
|
|
|
return "If the constructor allocate memory then the destructor must deallocate it.\n";
|
2009-06-12 12:19:37 +02:00
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
};
|
|
|
|
|
2009-06-08 20:20:43 +02:00
|
|
|
|
2009-06-16 22:01:04 +02:00
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/** @brief detect simple memory leaks for struct members */
|
2009-06-16 22:01:04 +02:00
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckMemoryLeakStructMember : private Check, private CheckMemoryLeak {
|
2009-06-16 22:01:04 +02:00
|
|
|
public:
|
2014-11-20 14:20:09 +01:00
|
|
|
CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(0, 0, 0) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-06-16 22:01:04 +02:00
|
|
|
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakStructMember(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
2014-11-20 14:20:09 +01:00
|
|
|
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog, settings) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-06-16 22:01:04 +02:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) {
|
2010-04-08 22:56:34 +02:00
|
|
|
CheckMemoryLeakStructMember checkMemoryLeak(tokenizr, settings, errLog);
|
2009-06-16 22:01:04 +02:00
|
|
|
checkMemoryLeak.check();
|
|
|
|
}
|
|
|
|
|
2009-07-19 16:51:31 +02:00
|
|
|
void check();
|
2009-06-16 22:01:04 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
2011-05-11 18:19:14 +02:00
|
|
|
/** Is local variable allocated with malloc? */
|
2012-05-03 10:43:47 +02:00
|
|
|
static bool isMalloc(const Variable *variable);
|
2011-05-11 18:19:14 +02:00
|
|
|
|
2012-05-03 10:43:47 +02:00
|
|
|
void checkStructVariable(const Variable * const variable);
|
2011-05-11 18:19:14 +02:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) const {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2009-06-16 22:01:04 +02:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2009-06-16 22:01:04 +02:00
|
|
|
return "Memory leaks (struct members)";
|
|
|
|
}
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
std::string classInfo() const {
|
2012-08-26 16:22:46 +02:00
|
|
|
return "Don't forget to deallocate struct members\n";
|
2009-06-16 22:01:04 +02:00
|
|
|
}
|
|
|
|
};
|
2010-11-12 21:09:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @brief detect simple memory leaks (address not taken) */
|
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckMemoryLeakNoVar : private Check, private CheckMemoryLeak {
|
2010-11-12 21:09:34 +01:00
|
|
|
public:
|
2014-11-20 14:20:09 +01:00
|
|
|
CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(0, 0, 0) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2010-11-12 21:09:34 +01:00
|
|
|
|
|
|
|
CheckMemoryLeakNoVar(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
2014-11-20 14:20:09 +01:00
|
|
|
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog, settings) {
|
2013-08-07 16:27:37 +02:00
|
|
|
}
|
2010-11-12 21:09:34 +01:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) {
|
2010-11-12 21:09:34 +01:00
|
|
|
CheckMemoryLeakNoVar checkMemoryLeak(tokenizr, settings, errLog);
|
|
|
|
checkMemoryLeak.check();
|
|
|
|
}
|
|
|
|
|
|
|
|
void check();
|
|
|
|
|
2012-03-15 18:52:51 +01:00
|
|
|
private:
|
2014-01-03 10:12:32 +01:00
|
|
|
/**
|
|
|
|
* @brief %Check if a call to an allocation function like malloc() is made and its return value is not assigned.
|
|
|
|
* @param scope The scope of the function to check.
|
|
|
|
*/
|
|
|
|
void checkForUnusedReturnValue(const Scope *scope);
|
2012-03-15 18:52:51 +01:00
|
|
|
|
2015-01-04 11:07:53 +01:00
|
|
|
/**
|
|
|
|
* @brief %Check if an exception could cause a leak in an argument constructed with shared_ptr/unique_ptr.
|
|
|
|
* @param scope The scope of the function to check.
|
|
|
|
*/
|
|
|
|
void checkForUnsafeArgAlloc(const Scope *scope);
|
|
|
|
|
2012-03-15 18:52:51 +01:00
|
|
|
void functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall);
|
2014-01-03 10:12:32 +01:00
|
|
|
void returnValueNotUsedError(const Token* tok, const std::string &alloc);
|
2015-01-04 11:07:53 +01:00
|
|
|
void unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string &objType);
|
2012-03-15 18:52:51 +01:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void getErrorMessages(ErrorLogger *e, const Settings *settings) const {
|
2012-03-14 23:44:04 +01:00
|
|
|
CheckMemoryLeakNoVar c(0, settings, e);
|
|
|
|
|
|
|
|
c.functionCallLeak(0, "funcName", "funcName");
|
2014-01-03 10:12:32 +01:00
|
|
|
c.returnValueNotUsedError(0, "funcName");
|
2015-01-04 11:07:53 +01:00
|
|
|
c.unsafeArgAllocError(0, "funcName", "shared_ptr", "int");
|
2012-03-14 23:44:04 +01:00
|
|
|
}
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2010-11-12 21:09:34 +01:00
|
|
|
return "Memory leaks (address not taken)";
|
|
|
|
}
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
std::string classInfo() const {
|
2012-08-26 16:22:46 +02:00
|
|
|
return "Not taking the address to allocated memory\n";
|
2010-11-12 21:09:34 +01:00
|
|
|
}
|
|
|
|
};
|
2009-07-17 10:49:01 +02:00
|
|
|
/// @}
|
2008-12-18 22:28:57 +01:00
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#endif // checkmemoryleakH
|