/* ************************************************************************* ArmageTron -- Just another Tron Lightcycle Game in 3D. Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) ************************************************************************** This program is f.ree 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 2 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 along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *************************************************************************** */ // LoadLibrary #include "defs.h" #include #include #include // need basic C IO since STL IO does memory management #include "tMemManager.h" #include "tError.h" #ifdef WIN32 #ifdef _MSC_VER #include #include #ifdef _DEBUG #undef _DEBUG #endif #include #pragma warning (disable : 4073) #pragma init_seg(lib) #endif static CRITICAL_SECTION mutex; #endif #ifndef DONTUSEMEMMANAGER #define NEW #endif #ifdef DEBUG #define LEAKFINDER #ifdef LEAKFINDER #define PROFILER #endif #ifdef WIN32 //#define MEM_DEB_SMALL //#define MEM_DEB //#define DOUBLEFREEFINDER #endif //#define MEM_DEB_SMALL //#define MEM_DEB //#define DOUBLEFREEFINDER #endif static bool reported=false; void leak(){ if (!reported) { reported=true; #ifdef DEBUG #ifdef WIN32 MessageBox (NULL, "Memory leak detected!" , "Memory Leak", MB_OK); #else std::cerr << "\n\nMemory leak detected!\n\n"; #endif #endif tMemMan::Profile(); } } #include "tList.h" class memblock; #ifdef DEBUG #define SAFETYBYTES 16 #else #define SAFETYBYTES 0 #endif #define PAD 197 class tMemManager{ friend class memblock; public: tMemManager(int size, int blocksize); tMemManager(int size); ~tMemManager(); void * Alloc(); static void * AllocDefault(size_t size); static void Dispose(void *p, bool keep=false); void complete_Dispose(memblock *m); void Check(); // check integrity private: int Lower(int i){ // the element below i in the heap if(i%2==0) // just to make sure what happens; you never know what 1/2 is.. return i/2-1; else return (i-1)/2; } bool SwapIf(int i,int j); // swaps heap elements i and j if they are // in wrong order; only then, TRUE is returned. // i is assumed to lie lower in the heap than j. void SwapDown(int j); // swap element j as far down as it may go. void SwapUp(int i); // swap element j as far up as it must. //#ifdef MEM_DEB void CheckHeap(); // checks the heap structure //#endif static int UpperL(int i){return 2*i+1;} // the elements left and static int UpperR(int i){return 2*i+2;} // right above i void Insert(memblock *b); // starts to manage object e void Remove(memblock *b); // stops (does not delete e) memblock * Remove(int i); // stops to manage object i, wich is returned. void Replace(int i); // puts element i to the right place (if the // rest of the heap has correct order) void Replace(memblock *e); int size; int blocksize; tList blocks; tList full_blocks; int semaphore; }; static bool inited=false; #ifdef LEAKFINDER #include #define MAXCHECKSUM 100001 static int checksum=-1; static int counter[MAXCHECKSUM]; static int leaks[MAXCHECKSUM]; #ifdef PROFILER static const char *checksum_fileName[MAXCHECKSUM]; static const char *checksum_classname[MAXCHECKSUM]; static int checksum_line[MAXCHECKSUM]; static int checksum_blocks[MAXCHECKSUM]; static int checksum_bytes[MAXCHECKSUM]; #endif static char *leakname="leak.log"; static bool checkleaks=true; static const char *fileName="XXX"; static const char *classname="XXX"; static int line; static bool array; #endif void begin_checkleaks(){ #ifdef LEAKFINDER checkleaks=true; #endif } struct chunkinfo{ unsigned char pos:8; // our position in the block unsigned char occupied:1; // flag unsigned char size_in_dwords:7; // size unsigned char next:8; // next element of same state unsigned char prev:8; // .... #ifdef LEAKFINDER int checksum; int counter; bool array; #endif #ifdef PROFILER size_t realSize; #endif }; // the heap elements. class memblock{ public: // everything is local to this file anyway... int value; // our value (the number of free slots). // lower values are lower in the heap. int hID; // the id in the heap tMemManager *myman; int size; unsigned char first_free; ~memblock(){ if (myman) myman->blocks.Remove(this,hID); //tASSERT(myman->blocksize == value); } chunkinfo & chunk(int i){ tASSERT(i>=0 && iblocksize); return *( (chunkinfo *)(void *) ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i) ); } char * safety(int i){ tASSERT(i>=0 && iblocksize); return ( ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i) +sizeof(chunkinfo)+size ); } void * data(int i){ tASSERT(i>=0 && iblocksize); return (void *) ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i + sizeof(chunkinfo)); } memblock(tMemManager *man):value(man->blocksize),hID(-1),myman(man){ // std::cout << "new memblock..\n"; size=man->size; myman->blocks.Add(this,hID); // TODO: init linked list for (int i=man->blocksize-1 ; i>=0 ; i--){ if (iblocksize-1) chunk(i).next=i+2; else chunk(i).next=0; if (i>0) chunk(i).prev=i; else chunk(i).prev=0; chunk(i).pos = i; chunk(i).occupied = false; chunk(i).size_in_dwords = size >> 2; for (int j=SAFETYBYTES-1;j>=0;j--) safety(i)[j]=(j ^ PAD); } #ifdef MEM_DEB Check(); #endif first_free=1; } void *Alloc(){ #ifdef MEM_DEB_SMALL Check(); #endif tASSERT(value>0); value--; // TODO: faster using linked list int ret=-1; /* for (int i=myman->blocksize-1 ; i>=0 ; i--) if (!chunk(i).occupied){ // chunk(i).occupied=true; ret=i; i=-1; // return data(i); }*/ ret=first_free-1; tASSERT(ret>=0); // tASSERT(_CrtCheckMemory()); chunk(ret).occupied=true; first_free=chunk(ret).next; // tASSERT(_CrtCheckMemory()); if (first_free>0) chunk(first_free-1).prev=0; chunk(ret).next=chunk(ret).prev=0; // tASSERT(_CrtCheckMemory()); #ifdef LEAKFINDER if (checksum >= 0){ tASSERT(checksum < MAXCHECKSUM); #ifdef PROFILER if (!counter[checksum]){ checksum_fileName [checksum] = fileName; checksum_classname[checksum] = classname; checksum_line [checksum] = line; } checksum_blocks[checksum]++; checksum_bytes[checksum]+=size; chunk(ret).realSize = size; #endif chunk(ret).array=array; chunk(ret).checksum=checksum; chunk(ret).counter =++counter[checksum]; static int count =0; if (checkleaks && counter[checksum] == leaks[checksum]){ count ++; if (count <= 0) { std::cerr << "one of the endless ignored objects that were leaky last time created!\n"; } else if (count <= 1) { std::cerr << "Object that was leaky last time created!\n"; st_Breakpoint(); } else if (count <= 3) { std::cerr << "One more object that was leaky last time created!\n"; st_Breakpoint(); } else { std::cerr << "one of the endless objects that were leaky last time created!\n"; // st_Breakpoint(); } } } #endif #ifdef _DEBUG memchr(data(ret), 0xfedabaac, size>>2); #endif #ifdef MEM_DEB_SMALL Check(); #endif return data(ret); tASSERT(0); // we should never get here return NULL; } static memblock * Dispose(void *p, int &size,bool keep=false){ chunkinfo &c=((chunkinfo *)p)[-1]; size=c.size_in_dwords*4; #ifdef PROFILER if (c.checksum >=0 && c.checksum < MAXCHECKSUM){ checksum_blocks[c.checksum]--; checksum_bytes [c.checksum]-=c.realSize; } #else #ifdef LEAKFINDER tASSERT(c.checksum>=-1 && c.checksum < MAXCHECKSUM); #endif #endif #ifndef WIN32 // grr. on windows, this assertion fails on calls from STL. tASSERT( c.array == array ); #endif if (size==0){ bool o = c.occupied; // tASSERT(c.occupied); c.occupied=false; if (o) free(&c); return NULL; } tASSERT(c.occupied == 1); if (!c.occupied) return NULL; memblock *myblock=( (memblock *)(void *) ( ( (char *)(void *)p ) - ( (sizeof(chunkinfo)+size+SAFETYBYTES)*c.pos + sizeof(chunkinfo) ) ) ) - 1; c.occupied=false; #ifndef DOUBLEFREEFINDER if (keep) return NULL; #ifdef WIN32 EnterCriticalSection(&mutex); #endif tASSERT(myblock -> value < myblock->myman->blocksize); c.prev=0; c.next=myblock->first_free; myblock->first_free=c.pos+1; if (c.next) myblock->chunk(c.next-1).prev=c.pos+1; myblock->value++; #endif // TODO: use linked list return myblock; } static memblock * create(tMemManager *man){ //tASSERT(_CrtCheckMemory()); void *mem = malloc(man->blocksize * (SAFETYBYTES + man->size + sizeof(chunkinfo)) + sizeof(memblock)); // tASSERT(_CrtCheckMemory()); return new(mem) memblock(man); } static void destroy(memblock * b){ b->~memblock(); free((void *)b); } void Check(){ tASSERT (size == myman->size); tASSERT (value >=0); tASSERT (value <= myman->blocksize); for(int i=myman->blocksize-1;i>=0;i--){ tASSERT(chunk(i).pos == i); for (int j=SAFETYBYTES-1;j>=0;j--){ char a=safety(i)[j]; char b=j^PAD; tASSERT(a==b); } } } #ifdef LEAKFINDER void dumpleaks(std::ostream &s){ for (int i=myman->blocksize-1;i>=0;i--) if (chunk(i).occupied){ s << chunk(i).checksum << " " << chunk(i).counter << '\n'; leak(); } } #endif }; // *********************************************** bool tMemManager::SwapIf(int i,int j){ if (i==j || i<0) return false; // safety memblock *e1=blocks(i),*e2=blocks(j); if (e1->value > e2->value){ Swap(blocks(i),blocks(j)); e1->hID=j; e2->hID=i; return true; } else return false; } tMemManager::~tMemManager(){ #ifdef LEAKFINDER if (inited){ // l÷sche das ding std::ofstream lw(leakname); lw << "\n\n"; tMemMan::Profile(); } #endif #ifdef WIN32 if (inited) DeleteCriticalSection(&mutex); #endif inited = false; //tASSERT (full_blocks.Len() == 0); int i; for (i=blocks.Len()-1;i>=0;i--){ if (blocks(i)->value==blocksize) memblock::destroy(blocks(i)); else{ #ifdef LEAKFINDER static bool warn = true; if ( warn ) { std::cout << "Memmanager warning: leaving block untouched.\n"; } std::ofstream l(leakname,std::ios::app); blocks(i)->dumpleaks(l); #endif } } for (i=full_blocks.Len()-1;i>=0;i--){ if (full_blocks(i)->value==blocksize) memblock::destroy(full_blocks(i)); else{ #ifdef LEAKFINDER std::cout << "Memmanager warning: leaving block untouched.\n"; std::ofstream l(leakname,std::ios::app); full_blocks(i)->dumpleaks(l); #endif } } } tMemManager::tMemManager(int s,int bs):size(s),blocksize(s){ // std::cout << sizeof(chunkinfo); if (blocksize>255) blocksize=255; semaphore = 1; #ifdef WIN32 if (!inited) InitializeCriticalSection(&mutex); #endif inited = true; } tMemManager::tMemManager(int s):size(s){//,blocks(1000),full_blocks(1000){ inited = false; blocks.SetLen(0); full_blocks.SetLen(0); blocksize=16000/(s+sizeof(chunkinfo)+SAFETYBYTES); if (blocksize>252) blocksize=252; // std::cout << sizeof(chunkinfo) << ',' << s << ',' << blocksize << '\n'; semaphore = 1; #ifdef LEAKFINDER if (size == 0){ std::ifstream l(leakname); while (l.good() && !l.eof()){ int cs,ln; l >> cs >> ln; if (cs>=0 && cs < MAXCHECKSUM && (ln < leaks[cs] || leaks[cs] == 0)) leaks[cs]=ln; } } if (!inited){ // l÷sche das ding std::ofstream lw(leakname); lw << "\n\n"; } #endif #ifdef WIN32 if (!inited) InitializeCriticalSection(&mutex); #endif inited = true; } //#ifdef MEM_DEB void tMemManager::CheckHeap(){ for(int i=blocks.Len()-1;i>0;i--){ memblock *current=blocks(i); memblock *low=blocks(Lower(i)); if (Lower(UpperL(i))!=i || Lower(UpperR(i))!=i) tERR_ERROR_INT("Error in lower/upper " << i << "!"); if (low->value>current->value) tERR_ERROR_INT("Heap structure corrupt!"); } } //#endif void tMemManager::SwapDown(int j){ int i=j; // e is now at position i. swap it down // as far as it goes: do{ j=i; i=Lower(j); } while(SwapIf(i,j)); // mean: relies on the fact that SwapIf returns -1 // if i<0. #ifdef MEM_DEB CheckHeap(); #endif } void tMemManager::SwapUp(int i){ #ifdef MEM_DEB // static int su=0; //if (su%100 ==0 ) // std::cout << "su=" << su << '\n'; // if (su > 11594 ) // con << "su=" << su << '\n'; // su ++; #endif int ul,ur; bool goon=1; while(goon && UpperL(i)=blocks.Len() || blocks(ul)->value < blocks(ur)->value){ goon=SwapIf(i,ul); i=ul; } else{ goon=SwapIf(i,ur); i=ur; } } #ifdef MEM_DEB CheckHeap(); #endif } void tMemManager::Insert(memblock *e){ blocks.Add(e,e->hID); // relies on the implementation of List: e is // put to the back of the heap. SwapDown(blocks.Len()-1); // bring it to the right place #ifdef MEM_DEB CheckHeap(); #endif } void tMemManager::Remove(memblock *e){ int i=e->hID; if(i<0 || this != e->myman) tERR_ERROR_INT("Element is not in this heap!"); Remove(i); #ifdef MEM_DEB CheckHeap(); #endif } void tMemManager::Replace(int i){ if (i>=0 && i < blocks.Len()){ if (i==0 || blocks(i)->value > blocks(Lower(i))->value) SwapUp(i); // put it up where it belongs else SwapDown(i); #ifdef MEM_DEB CheckHeap(); #endif } } void tMemManager::Replace(memblock *e){ int i=e->hID; if(i<0 || this != e->myman) tERR_ERROR_INT("Element is not in this heap!"); Replace(i); #ifdef MEM_DEB CheckHeap(); #endif } memblock * tMemManager::Remove(int i){ if (i>=0 && ihID); // now we have an misplaced element at pos i. (if i was not at the end..) if (isize == size); void *mem = block->Alloc(); //tASSERT(_CrtCheckMemory()); if (block->value == 0){ Remove(block); full_blocks.Add(block,block->hID); } #ifdef WIN32 LeaveCriticalSection(&mutex); #endif semaphore++; return mem; } void tMemManager::complete_Dispose(memblock *block){ #ifdef MEM_DEB_SMALL block->Check(); #endif semaphore--; if (semaphore>=0){ if (block->value == 1){ full_blocks.Remove(block,block->hID); Insert(block); } else{ Replace(block); } } //else // tASSERT(0); semaphore++; #ifdef MEM_DEB_SMALL block->Check(); #endif } void tMemManager::Check(){ if ( !inited ) return; CheckHeap(); int i; for (i=blocks.Len()-1;i>=0;i--) { blocks(i)->Check(); tASSERT (blocks(i)->myman == this); tASSERT (blocks(i)->size == size); } for (i=full_blocks.Len()-1;i>=0;i--) { if ( full_blocks(i) ) { full_blocks(i)->Check(); tASSERT (full_blocks(i)->myman == this); tASSERT (full_blocks(i)->size == size); } } } #define MAX_SIZE 109 static tMemManager memman[MAX_SIZE+1]={ tMemManager(0), tMemManager(4), tMemManager(8), tMemManager(12), tMemManager(16), tMemManager(20), tMemManager(24), tMemManager(28), tMemManager(32), tMemManager(36), tMemManager(40), tMemManager(44), tMemManager(48), tMemManager(52), tMemManager(56), tMemManager(60), tMemManager(64), tMemManager(68), tMemManager(72), tMemManager(76), tMemManager(80), tMemManager(84), tMemManager(88), tMemManager(92), tMemManager(96), tMemManager(100), tMemManager(104), tMemManager(108), tMemManager(112), tMemManager(116), tMemManager(120), tMemManager(124), tMemManager(128), tMemManager(132), tMemManager(136), tMemManager(140), tMemManager(144), tMemManager(148), tMemManager(152), tMemManager(156), tMemManager(160), tMemManager(164), tMemManager(168), tMemManager(172), tMemManager(176), tMemManager(180), tMemManager(184), tMemManager(188), tMemManager(192), tMemManager(196), tMemManager(200), tMemManager(204), tMemManager(208), tMemManager(212), tMemManager(216), tMemManager(220), tMemManager(224), tMemManager(228), tMemManager(232), tMemManager(236), tMemManager(240), tMemManager(244), tMemManager(248), tMemManager(252), tMemManager(256), tMemManager(260), tMemManager(264), tMemManager(268), tMemManager(272), tMemManager(276), tMemManager(280), tMemManager(284), tMemManager(288), tMemManager(292), tMemManager(296), tMemManager(300), tMemManager(304), tMemManager(308), tMemManager(312), tMemManager(316), tMemManager(320), tMemManager(324), tMemManager(328), tMemManager(332), tMemManager(336), tMemManager(340), tMemManager(344), tMemManager(348), tMemManager(352), tMemManager(356), tMemManager(360), tMemManager(364), tMemManager(368), tMemManager(372), tMemManager(376), tMemManager(380), tMemManager(384), tMemManager(388), tMemManager(392), tMemManager(396), tMemManager(400), tMemManager(404), tMemManager(408), tMemManager(412), tMemManager(416), tMemManager(420), tMemManager(424), tMemManager(428), tMemManager(432), tMemManager(436) }; void tMemManager::Dispose(void *p,bool keep){ int size; if (!p) return; memblock *block = memblock::Dispose(p,size,keep); #ifndef DOUBLEFREEFINDER if (inited && block){ memman[size >> 2].complete_Dispose(block); #ifdef WIN32 LeaveCriticalSection(&mutex); #endif } #else block = 0; #endif } void *tMemManager::AllocDefault(size_t s){ #ifdef LEAKFINDER void *ret=malloc(s+sizeof(chunkinfo));//,classname,fileName,line); ((chunkinfo *)ret)->checksum=checksum; ((chunkinfo *)ret)->array=array; #ifdef PROFILER ((chunkinfo *)ret)->realSize=s; if (!counter[checksum]){ checksum_fileName [checksum] = fileName; checksum_classname[checksum] = classname; checksum_line [checksum] = line; } checksum_blocks[checksum]++; checksum_bytes[checksum]+=s; #endif #else void *ret=malloc(s+sizeof(chunkinfo)); #endif ((chunkinfo *)ret)->size_in_dwords=0; ((chunkinfo *)ret)->occupied=true; ret = ((chunkinfo *)ret)+1; return ret; } void *tMemMan::Alloc(size_t s){ #ifndef DONTUSEMEMMANAGER #ifdef MEM_DEB #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif Check(); #endif void *ret; if (inited && s < (MAX_SIZE << 2)) ret=memman[((s+3)>>2)].Alloc(); else{ ret=tMemManager::AllocDefault(s); } #ifdef MEM_DEB Check(); #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif #endif return ret; #else return malloc(s); #endif } void tMemMan::DisposeButKeep(void *p){ #ifndef DONTUSEMEMMANAGER #ifdef MEM_DEB #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif Check(); #endif tMemManager::Dispose(p,true); #ifdef MEM_DEB Check(); #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif #endif #endif } void tMemMan::Dispose(void *p){ #ifndef DONTUSEMEMMANAGER #ifdef MEM_DEB #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif Check(); #endif tMemManager::Dispose(p); #ifdef MEM_DEB Check(); #ifdef WIN32 tASSERT(_CrtCheckMemory()); #endif #endif #else free(p); #endif } void tMemMan::Check(){ if (!inited) return; #ifdef WIN32 EnterCriticalSection(&mutex); #endif for (int i=MAX_SIZE;i>=0;i--) memman[i].Check(); #ifdef WIN32 LeaveCriticalSection(&mutex); #endif } /* void* operator new (unsigned int size) { //return zmalloc.Malloc (size, "UNKNOWN", "zMemory.cpp", 49); // return malloc(size); return tMemManager::AllocDefault(size); }; void operator delete(void *ptr) { if (ptr) tMemManager::Dispose(ptr); // zmalloc.Free(ptr); }; */ #ifdef NEW /* void * operator new( unsigned int cb, int nBlockUse, const char * szFileName, int nLine ) { return operator new(cb, "xxx", szFileName, nLine); } */ #ifdef WIN32 #ifdef DEDICATED #ifdef DEBUG #if 0 void * operator new( size_t size, int nBlockUse, const char * file, int l ) { #ifdef LEAKFINDER fileName=file; classname="XXX"; line=l; checksum = #ifndef PROFILER size + #endif line * 19671; int c=1379; while (*file){ checksum = (checksum + (*file)*c) % MAXCHECKSUM; c = (c * 79 ) % MAXCHECKSUM; file++; } #ifdef PROFILER while (checksum_fileName[checksum] && (checksum_fileName[checksum] != fileName || checksum_line[checksum] != line)) checksum = (checksum+1) % MAXCHECKSUM; #endif #endif return tMemMan::Alloc(size); // return _nh_malloc_dbg( cb, 1, nBlockUse, szFileName, nLine ); } #endif #endif #endif #endif void* _cdecl operator new (size_t size) THROW_BADALLOC{ #ifdef LEAKFINDER checksum = size; array = false; #endif return tMemMan::Alloc(size); }; void _cdecl operator delete(void *ptr) THROW_NOTHING{ #ifdef LEAKFINDER checksum = -1; array = false; #endif if (ptr) tMemMan::Dispose(ptr); }; void operator delete(void *ptr,bool keep) THROW_NOTHING{ #ifdef LEAKFINDER checksum = -1; array = false; #endif if (ptr){ if (keep) tMemMan::DisposeButKeep(ptr); else tMemMan::Dispose(ptr); } }; void* operator new (size_t size,const char *classn,const char *file,int l) THROW_BADALLOC{ #ifdef LEAKFINDER fileName=file; classname=classn; line=l; array = false; checksum = #ifndef PROFILER size + #endif line * 19671; int c=1379; while (*file){ checksum = (checksum + (*file)*c) % MAXCHECKSUM; c = (c * 79 ) % MAXCHECKSUM; file++; } while (*classn){ checksum = (checksum + (*classn)*c) % MAXCHECKSUM; c = (c * 79 ) % MAXCHECKSUM; classn++; } #ifdef PROFILER while (checksum_fileName[checksum] && (checksum_fileName[checksum] != fileName || checksum_line[checksum] != line)) checksum = (checksum+1) % MAXCHECKSUM; #endif #endif return tMemMan::Alloc(size); } void operator delete (void *ptr,const char *classname,const char *file,int line) THROW_NOTHING{ #ifdef LEAKFINDER checksum = 0; array = false; #endif if (ptr) tMemMan::Dispose(ptr); } void* operator new[] (size_t size) THROW_BADALLOC{ #ifdef LEAKFINDER checksum = size; array = true; #endif return tMemMan::Alloc(size); }; void operator delete[](void *ptr) THROW_NOTHING { #ifdef LEAKFINDER checksum = -1; array = true; #endif if (ptr) tMemMan::Dispose(ptr); }; void* operator new[] (size_t size,const char *classn,const char *file,int l) THROW_BADALLOC{ #ifdef LEAKFINDER fileName=file; classname=classn; line=l; array = true; checksum = #ifndef PROFILER size + #endif line * 19671; int c=1379; while (*file){ checksum = (checksum + (*file)*c) % MAXCHECKSUM; c = (c * 79 ) % MAXCHECKSUM; file++; } while (*classn){ checksum = (checksum + (*classn)*c) % MAXCHECKSUM; c = (c * 79 ) % MAXCHECKSUM; classn++; } #ifdef PROFILER while (checksum_fileName[checksum] && (checksum_fileName[checksum] != fileName || checksum_line[checksum] != line)) checksum = (checksum+1) % MAXCHECKSUM; #endif #endif return tMemMan::Alloc(size); } void operator delete[] (void *ptr,const char *classname,const char *file,int line) THROW_NOTHING{ #ifdef LEAKFINDER checksum = 0; array = true; #endif if (ptr) tMemMan::Dispose(ptr); } #endif #ifdef PROFILER static int compare(const void *a, const void *b){ int A = checksum_bytes[*((int *)a)]; int B = checksum_bytes[*((int *)b)]; if (AB) return 1; return 0; } //#define PRINT(blocks, size, c, f, l, cs) s << std::setw(6) << blocks << "\t" << std::setw(9) << size << "\t" << std::setw(20) << c << "\t" << std::setw(70) << f << "\t" << std::setw(6) << l << "\t" << cs << "\n" //#define PRINT(blocks, size, c, f, l, cs) fprintf("%d:6% std::setw(6) << blocks << "\t" << std::setw(9) << size << "\t" << std::setw(20) << c << "\t" << std::setw(70) << f << "\t" << std::setw(6) << l << "\t" << cs << "\n" #endif #ifdef WIN32 #define snprintf _snprintf #endif void tMemMan::Profile(){ #ifdef PROFILER int sort_checksum[MAXCHECKSUM]; int size=0,i; for (i=MAXCHECKSUM-1;i>=0;i--) if (checksum_blocks[i]) sort_checksum[size++] = i; qsort(sort_checksum, size, sizeof(int), &compare); static int num=1; char name[100]; snprintf( name, 99, "memprofile%d.txt", num++ ); // std::ostringstream fn; // fn << "memprofile" << num++ << ".txt" << '\0'; FILE *f = fopen( name, "w" ); // fprintf( f, "%d\t%d\t%d\t%s\t%s\t%d\t%d\t\n", ) int total_blocks=0,total_bytes =0; for (i=size-1; i>=0; i--) { int cs = sort_checksum[i]; const char *fn = checksum_fileName[cs]; const char *cn = checksum_classname[cs]; if (!fn) fn = "XXX"; if (!cn) cn = "XXX"; fprintf( f, "%d\t%d\t%30s\t%80s\t%d\t%d\t\n", checksum_blocks[cs], checksum_bytes[cs],cn, fn , checksum_line[cs], cs ); // PRINT(checksum_blocks[cs], checksum_bytes[cs],cn, fn , checksum_line[cs], cs); total_blocks += checksum_blocks[cs]; total_bytes += checksum_bytes[cs]; } fclose( f ); /* std::ofstream s( name ); s.setf(std::ios::left); PRINT("Blocks", "Bytes", "Class", "File", "Line", "Checksum"); int total_blocks=0,total_bytes =0; for (i=size-1; i>=0; i--) { int cs = sort_checksum[i]; const char *fn = checksum_fileName[cs]; const char *cn = checksum_classname[cs]; if (!fn) fn = "XXX"; if (!cn) cn = "XXX"; PRINT(checksum_blocks[cs], checksum_bytes[cs],cn, fn , checksum_line[cs], cs); total_blocks += checksum_blocks[cs]; total_bytes += checksum_bytes[cs]; } s << "\n\n"; PRINT (total_blocks, total_bytes, "Total" , "", "", ""); */ #endif }