/** ****************************************************************************** @file /common/mm.cpp @brief Memory manager/ helpers/ debug functions @author Vajicek @version 0.1 ******************************************************************************/ #include "common/mm.h" #include "common/utils.h" #include "common/mutex.h" #include #include #include #include /// Zamek na pristup ke sprave pameti static TMutex memmutex; /////////////////////////////////////////////////////////////////////////////// void* CheckedMemAlloc(size_t size){ void* ret = NULL; ret = malloc(size); if( !ret && size ){ CONSOLE("Insufficient memory! Commiting suicide..Farewell\n"); exit(0xDEAD); } return ret; } void* CheckedMemRealloc(void *mem, size_t size){ void* ret = NULL; ret = realloc(mem, size); if( !ret && size ){ CONSOLE("Insufficient memory! Commiting suicide...Farewell\n"); exit(0xDEAD); } return ret; } #ifdef K8_MM_MALLOCCHECK void* operator new(size_t s){ return KMemAlloc(s); } #endif /////////////////////////////////////////////////////////////////////////////// #ifdef K8_MM_NEWDEBUG void* operator new(size_t s){ //jakykoliv debug kod(ktery neni v DebugMemAlloc) return KMemAlloc(s); } void operator delete(void* p){ //jakykoliv debug kod(ktery neni v DebugMemFree) KMemFree(p); } #endif /////////////////////////////////////////////////////////////////////////////// #ifdef K8_MM_DEBUG void* DebugClassHelper::operator new(size_t s){ //jakykoliv debug kod(ktery neni v DebugMemAlloc) return KMemAlloc(s); } void DebugClassHelper::operator delete(void* p){ //jakykoliv debug kod(ktery neni v DebugMemFree) KMemFree(p); } #endif /////////////////////////////////////////////////////////////////////////////// //pocitadlo v log souboru void* DebugMemAlloc(size_t size){ FILE* f = NULL; static int initialized = 0; int mem_allocs = 0; if(!size)return NULL; if(initialized) { f = fopen(MEMDBG_FILE,"r"); if( f ) { fscanf(f,"%d",&mem_allocs); fclose(f); } } else initialized = 1; void* ret; ret = malloc(size); if(ret){ f = fopen(MEMDBG_FILE,"w"); if( f ) { fprintf(f,"%d",mem_allocs + 1); fclose(f); } } return ret; } // pouze k moznosti mit vsude Mem1 nebo Mem2 fce void* DebugMemRealloc(void *mem,size_t size){ if(!size)return NULL; return realloc(mem, size); } // odcita pocitadlo void DebugMemFree(void* mem){ FILE* f = NULL; int mem_allocs = 0; if(!mem) { return; } f = fopen(MEMDBG_FILE,"r"); if( f ) { fscanf(f,"%d",&mem_allocs); fclose(f); } f = fopen(MEMDBG_FILE,"w"); if( f ) { fprintf(f,"%d",mem_allocs - 1); fclose(f); } free(mem); } /////////////////////////////////////////////////////////////////////////////// std::vector amem; //uklada do vektoru void* DebugMemAlloc2(size_t size){ void* ret; if(!size)return NULL; ret = malloc(size); amem.push_back(ret); return ret; } //odstranuje z vektoru void DebugMemFree2(void* mem){ if(!mem)return; for(std::vector::iterator it = amem.begin(); it != amem.end(); it++) if(*it == mem) { amem.erase(it); break; } free(mem); } //maze z vektoru a pridava novy void* DebugMemRealloc2(void* mem,size_t size) { if(!mem)return NULL; // smazu ze seznamu for(std::vector::iterator it = amem.begin(); it != amem.end(); it++) if(*it == mem) { amem.erase(it); break; } if(!size)return NULL; void* ret; ret = realloc(mem,size); // a zas pridam amem.push_back(ret); return ret; } //vypisuje vektor void DumpAllocMem(){ std::vector::iterator it; FILE* f; f = fopen(MEMDBG_FILE,"w"); for(it = amem.begin(); it != amem.end(); it++) fprintf(f,"0x%p\n",*it); // 16kova soustava fclose(f); } /////////////////////////////////////////////////////////////////////////////// #ifdef K8_MM_DEBUG #define MIBUFFSIZE 1000000 #else #define MIBUFFSIZE 1 #endif #define FILEMSGLEN 20 #define MMREPORT //printf struct mem_info{ void* mem; size_t size; int line; char file[FILEMSGLEN]; }; static mem_info mi_buff[MIBUFFSIZE]; static int mi_c = 0; void remmi(void* p){ for(int i = 0; i < mi_c;i++){ if(mi_buff[i].mem == p){ mi_buff[i] = mi_buff[mi_c-1]; mi_c--; return; } } MMREPORT("%p not allocated\n", p); } void addmi(mem_info* mi){ if(mi_c >= MIBUFFSIZE){ MMREPORT("buffer full\n"); return; } mi_buff[mi_c] = *mi; mi_c++; } void DebugMemDAnew(void * mem) { memmutex.lock(); mem_info mi; mi.mem = mem; mi.line = -1; mi.size = 0; strcpy(mi.file,"? : new DA<>"); addmi(&mi); memmutex.unlock(); } void DebugMemDAdelete(void * mem) { memmutex.lock(); remmi(mem); memmutex.unlock(); } //pridava do logu void* DebugMemAlloc3(size_t size, int line, char* file){ memmutex.lock(); mem_info mi; size_t fl; if(!size) { memmutex.unlock(); return NULL; } mi.mem = malloc(size); mi.line = line; mi.size = size; fl = strlen(file); if(fl < FILEMSGLEN) strcpy(mi.file, file); else strcpy(mi.file, file + fl - FILEMSGLEN +1); addmi(&mi); memmutex.unlock(); return mi.mem; } //odebira void DebugMemFree3(void* mem){ memmutex.lock(); if(mem){ remmi(mem); free(mem); } memmutex.unlock(); } //prida a odebere void* DebugMemRealloc3(void* mem,size_t size,int line, char* file) { memmutex.lock(); mem_info mi; size_t fl; // if(!mem) { memmutex.unlock(); return NULL; } // smazu remmi(mem); // a zas pridam if(!size) { memmutex.unlock(); return NULL; } mi.mem = realloc(mem,size); mi.line = line; fl = strlen(file); if(fl < FILEMSGLEN) strcpy(mi.file, file); else strcpy(mi.file, file + fl - FILEMSGLEN + 1); addmi(&mi); memmutex.unlock(); return mi.mem; } //vypisuje presny log void DumpAllocMem2(){ memmutex.lock(); FILE* f = fopen(MEMDBG_FILE,"w"); if( f ) { for(int i = 0; i < mi_c;i++) fprintf(f,"%p of size %d bytes in file ..%s on line %d\n",mi_buff[i].mem, mi_buff[i].size, mi_buff[i].file, mi_buff[i].line); fclose(f); } memmutex.unlock(); } /////////////////////////////////////////////////////////////////////////////// //dolni cela cast logaritmu se zakladem 2 int log2(int i) { int r=0; while(i){ i=i>>1; r++; } return r; } #define LOG2(i,r) {int __j=i;r=0;while(__j){__j=__j>>1;r++;}} void* KExtArrayRealloc(void* mem, int unit_size, int new_count, int old_count){ int n,o; LOG2(new_count,n); LOG2(old_count,o); if( n != o ){ void* newmem = KMemAlloc((1<