diff options
Diffstat (limited to '3rdparty/clucene/src/CLucene/debug/memtracking.cpp')
-rw-r--r-- | 3rdparty/clucene/src/CLucene/debug/memtracking.cpp | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/3rdparty/clucene/src/CLucene/debug/memtracking.cpp b/3rdparty/clucene/src/CLucene/debug/memtracking.cpp new file mode 100644 index 000000000..544a125a5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/memtracking.cpp @@ -0,0 +1,371 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/util/Misc.h" + +bool _lucene_disable_debuglogging = true; //if LUCENE_ENABLE_CONSTRUCTOR_LOG is on, dont do log if this is true +bool _lucene_run_objectcheck = false; //run a memory check before deleting objects +int _lucene_counter_break = -1; //to break at this item, change this + //and put break points at points below + +CL_NS_USE(util) +CL_NS_DEF(debug) + +#ifdef LUCENE_ENABLE_MEMLEAKTRACKING +int32_t _instance_counter = 0; //counter for initnumber + +struct _file{ + int32_t refcount; ///times this has been used + char* value; ///reference to the the basefile +}; //structure for name counting +struct _pointers{ + _file* file; + int32_t initline; + int32_t initnumber; +};//structure for pointer-filename references + +typedef CL_NS(util)::CLSet<const char*,_file*,Compare::Char,Deletor::Dummy,Deletor::Void<_file> > defFile; +typedef CL_NS(util)::CLSet<LuceneBase*,_pointers*,Compare::Void<LuceneBase>,Deletor::Dummy,Deletor::Void<_pointers> > defPointer; +typedef CL_NS(util)::CLSet<const void*,_pointers*,Compare::Void<const void>,Deletor::Dummy,Deletor::Void<_pointers> > defVoid; + +DEFINE_MUTEX(memleak_lock) +defFile LuceneBase_Files(false,true); //list of filenames used +defPointer LuceneBase_Pointers(false,true); //list of pointers counted +defVoid LuceneBase_Voids(false,true); //list of arbitary data added + +//variables to trim filenames to just the base names +char _files_trim_string[CL_MAX_DIR]; +int32_t _files_trim_start=-1; + +//trim the filename and return the refcounted _file* structure +_file* get_file(const char* file){ + if ( _files_trim_start == -1 ){ + //this trims the start of the name file name so + //that the whole of the filename is not stored - more asthetic :) + //need to find the base + _files_trim_start = strlen(__FILE__) - 21; //(length of debug/memtracking.cpp) + strcpy(_files_trim_string,__FILE__); + _files_trim_string[_files_trim_start] = 0; + } + if ( strncmp(file,_files_trim_string,_files_trim_start) == 0 ){ + //this file should be within the same directory area as we found lucenebase.cpp + //to be, lets trim the start + file+=_files_trim_start; + } + + //now return an existing files structure (with refcount++) or create a new one + defFile::iterator itr = LuceneBase_Files.find((const char*)file); + if ( itr != LuceneBase_Files.end() ){ + _file* bf = itr->second; + bf->refcount++; + return bf; + }else{ + _file* ref = new _file; + ref->value = new char[strlen(file)+1]; //cannot use _CL_NEWARRAY otherwise recursion + strcpy(ref->value,file); + + ref->refcount = 1; + LuceneBase_Files.insert(pair<const char*,_file*>(ref->value,ref)); + return ref; + } +} + +void remove_file(_file* bf){ + bf->refcount--; + if ( bf->refcount <= 0 ){ + defFile::iterator fi = LuceneBase_Files.find(bf->value); + CND_PRECONDITION(fi!=LuceneBase_Files.end(),"fi==NULL"); + delete[] bf->value; + LuceneBase_Files.removeitr(fi); + } +} + +#ifdef LUCENE_ENABLE_CONSTRUCTOR_LOG + void constructor_log(const char* type,const char* file,const int line, const int size){ + if ( _lucene_disable_debuglogging ){ + FILE* f = fopen("clucene.log","a"); + char buf[CL_MAX_DIR+5]; + sprintf(buf,"%s,%s,%d,%d\n",type,file,line,size); + fwrite(buf,sizeof(char),strlen(buf),f); + fclose(f); + } + } + #define CONSTRUCTOR_LOG(type,file,line,size) constructor_log(type,file,line,size) +#else + #define CONSTRUCTOR_LOG(type,file,line,size) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// the _CLNEW&_CLDELETE new/delete operators +//////////////////////////////////////////////////////////////////////////////// +void* LuceneBase::operator new (size_t size, const char * file, int32_t line) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + void* p = malloc (size); + LuceneBase* lb = (LuceneBase*)p; + + //create the pointer struct + _file* br = get_file(file); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = line; + + //associate this object with the pointer + lb->__cl_initnum = bp->initnumber; + + //break if necessary + if ( _lucene_counter_break == lb->__cl_initnum ) + CLDebugBreak(); //put break point here + + //add the pointer object + LuceneBase_Pointers.insert(pair<LuceneBase*,_pointers*>(lb, bp)); + + CONSTRUCTOR_LOG("newobj",file,line,size); + return p; +} +void LuceneBase::operator delete (void *p, char const * file, int32_t line) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)p; + + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + if ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + + LuceneBase_Pointers.removeitr(itr); + }else{ + //break + } + free(p); +} + +/////////////////////////////////////////////////////////////////////////// +// the generic new/delete operators +/////////////////////////////////////////////////////////////////////////// +void* LuceneBase::operator new (size_t size) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + void* p = malloc (size); + LuceneBase* lb = (LuceneBase*)p; + + //create the pointer struct + _file* br = get_file("undefined"); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = -1; + + //associate this object with the pointer + lb->__cl_initnum = bp->initnumber; + + //break if necessary + if ( _lucene_counter_break == lb->__cl_initnum ) + CLDebugBreak(); + + //add the pointer object + LuceneBase_Pointers.insert(pair<LuceneBase*,_pointers*>(lb,bp)); + + CONSTRUCTOR_LOG("newobj","unknown",-1,size); + return p; +} +void LuceneBase::operator delete (void *p) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)p; + + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + if ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + LuceneBase_Pointers.removeitr(itr); + }else{ + CLDebugBreak(); + } + free(p); +} + +/////////////////////////////////////////////////////////////////////////// +// other memtracking functions +/////////////////////////////////////////////////////////////////////////// +void LuceneBase::__cl_unregister(const void* obj){ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)obj; + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + CND_PRECONDITION(itr != LuceneBase_Pointers.end(),"__cl_unregister object not found"); + _pointers* bp = itr->second; + LuceneBase_Pointers.removeitr(itr); +} + +void* LuceneBase::__cl_voidpadd(void* data, const char* file, int line,size_t size){ + SCOPED_LOCK_MUTEX(memleak_lock) + + _file* br = get_file(file); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = line; + + LuceneBase_Voids.insert(pair<void*,_pointers*>(data,bp)); + CONSTRUCTOR_LOG("newarr",file,line,size); + return data; +} +void LuceneBase::__cl_voidpremove(const void* data, const char* file, int line){ + SCOPED_LOCK_MUTEX(memleak_lock) + defVoid::iterator itr = LuceneBase_Voids.find(data); + if ( itr != LuceneBase_Voids.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + LuceneBase_Voids.removeitr(itr); + }else{ + printf("Data deleted when not added with _CL_NEWARRAY in %s at %d\n",file,line); + } +} + + +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +//The lucene base memory leak printout functions +//////////////////////////////////////////////////////////// +//static +void __internalcl_PrintUnclosedObject(bool isObject, string& sb,_pointers* bp,_file* bf, bool print){ + TCHAR ttmp[100]; + char atmp[100]; + + sb.append(" "); + { + _i64tot(bp->initnumber,ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + if ( isObject ){ + sb.append("(obj). "); + }else{ + sb.append(". "); + } + sb.append(bf->value); + sb.append(", line "); + { + _i64tot(bp->initline,ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + sb.append("\n"); + + if ( print && sb.length() > 0 ){ + printf("%s\n", sb.c_str()); + sb = ""; + } +} +char* __internalcl_GetUnclosedObjects(bool print){ + TCHAR ttmp[100]; + char atmp[100]; + SCOPED_LOCK_MUTEX(memleak_lock) + + string sb; + bool unknowns = false; + if ( LuceneBase_Pointers.size() > 0 ){ + { + _i64tot(LuceneBase_Pointers.size(),ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + sb.append(" clucene objects are still open\n"); + + defPointer::iterator itr = LuceneBase_Pointers.begin(); + while ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + _file* bf = bp->file; + + if ( bp->initline == -1 ) + unknowns = true; + __internalcl_PrintUnclosedObject(true, sb,bp,bf,print); + + ++itr; + } + + defVoid::iterator itr2 = LuceneBase_Voids.begin(); + while ( itr2 != LuceneBase_Voids.end() ){ + _pointers* bp = itr2->second; + _file* bf = bp->file; + + if ( bp->initline == -1 ) + unknowns = true; + __internalcl_PrintUnclosedObject(false, sb,bp,bf,print); + + itr2++; + } + } + + if ( unknowns == true ){ + sb.append("*** Some memory was not created with _CLNEW and was not tracked... ***\n"); + sb.append("*** Use _CLNEW instead of new when creating CLucene objects ***\n"); + sb.append("*** Memory may also have not been freed in the current context ***\n"); + } + + if ( print ){ + if ( sb.length() > 0 ){ + printf("%s\n", sb.c_str()); + sb = ""; + } + return NULL; + }else{ + if ( sb.length() > 0 ) + return STRDUP_AtoA(sb.c_str()); + else + return NULL; + } +} + +void LuceneBase::__cl_ClearMemory(){ + SCOPED_LOCK_MUTEX(memleak_lock) + + while ( LuceneBase_Files.size() > 0 ){ + defFile::iterator fi = LuceneBase_Files.begin(); + _file* f = fi->second; + delete[] f->value; + LuceneBase_Files.removeitr (fi); + } + LuceneBase_Pointers.clear(); + LuceneBase_Voids.clear(); +} +char* LuceneBase::__cl_GetUnclosedObjects(){ + return __internalcl_GetUnclosedObjects(false); +} +//static +int32_t LuceneBase::__cl_GetUnclosedObjectsCount(){ + return LuceneBase_Pointers.size(); +} + +const char* LuceneBase::__cl_GetUnclosedObject(int32_t item){ + SCOPED_LOCK_MUTEX(memleak_lock) + + defPointer::iterator itr=LuceneBase_Pointers.begin(); + int32_t i=0; + for ( ;itr!=LuceneBase_Pointers.end() && i<item ;itr++ ){ + ++i; + } + if ( itr != LuceneBase_Pointers.end() ) + return itr->second->file->value; + else + return NULL; +} +void LuceneBase::__cl_PrintUnclosedObjects(){ + __internalcl_GetUnclosedObjects(true); +} +//////////////////////////////////////////////////////////// + +#endif //LUCENE_ENABLE_MEMLEAKTRACKING +CL_NS_END |