/* * Copyright 2011 Range Networks, Inc. * All Rights Reserved. * * This software is distributed under multiple licenses; * see the COPYING file in the main directory for licensing * information for this specific distribuion. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. 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. */ #ifndef _MEMORYLEAK_ #define _MEMORYLEAK_ 1 #include #include "ScalarTypes.h" #include "Logger.h" namespace Utils { struct MemStats { // Enumerates the classes that are checked. // Redundancies are ok, for example, we check BitVector and also // several descendants of BitVector. enum MemoryNames { mZeroIsUnused, mVector, mVectorData, mBitVector, mByteVector, mByteVectorData, mRLCRawBlock, mRLCUplinkDataBlock, mRLCMessage, mRLCMsgPacketDownlinkDummyControlBlock, // Redundant with RLCMessage mTBF, mLlcEngine, mSgsnDownlinkMsg, mRachInfo, mPdpPdu, mFECDispatchInfo, mL3Frame, msignalVector, mSoftVector, mScramblingCode, mURlcDownSdu, mURlcPdu, // Must be last: mMax, }; int mMemTotal[mMax]; // In elements, not bytes. int mMemNow[mMax]; const char *mMemName[mMax]; MemStats(); void memChkNew(MemoryNames memIndex, const char *id); void memChkDel(MemoryNames memIndex, const char *id); void text(std::ostream &os); // We would prefer to use an unordered_map, but that requires special compile switches. // What a super great language. typedef std::map MemMapType; MemMapType mMemMap; }; extern struct MemStats gMemStats; extern int gMemLeakDebug; // This is a memory leak detector. // Use by putting RN_MEMCHKNEW and RN_MEMCHKDEL in class constructors/destructors, // or use the DEFINE_MEMORY_LEAK_DETECTOR class and add the defined class // as an ancestor to the class to be memory leak checked. struct MemLabel { std::string mccKey; virtual ~MemLabel() { Int_z &tmp = Utils::gMemStats.mMemMap[mccKey]; tmp = tmp - 1; } }; #if RN_DISABLE_MEMORY_LEAK_TEST #define RN_MEMCHKNEW(type) #define RN_MEMCHKDEL(type) #define RN_MEMLOG(type,ptr) #define DEFINE_MEMORY_LEAK_DETECTOR_CLASS(subClass,checkerClass) \ struct checkerClass {}; #else #define RN_MEMCHKNEW(type) { Utils::gMemStats.memChkNew(Utils::MemStats::m##type,#type); } #define RN_MEMCHKDEL(type) { Utils::gMemStats.memChkDel(Utils::MemStats::m##type,#type); } #define RN_MEMLOG(type,ptr) { \ static std::string key = format("%s_%s:%d",#type,__FILE__,__LINE__); \ (ptr)->/* MemCheck##type:: */ mccKey = key; \ Utils::gMemStats.mMemMap[key]++; \ } // TODO: The above assumes that checkclass is MemCheck ## subClass #define DEFINE_MEMORY_LEAK_DETECTOR_CLASS(subClass,checkerClass) \ struct checkerClass : public virtual Utils::MemLabel { \ checkerClass() { RN_MEMCHKNEW(subClass); } \ virtual ~checkerClass() { \ RN_MEMCHKDEL(subClass); \ } \ }; #endif } // namespace Utils #endif