123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 |
- // leave this as first line for PCH reasons...
- //
- #pragma warning( disable : 4786)
- #pragma warning( disable : 4100)
- #pragma warning( disable : 4663)
- #include <windows.h>
- #include "..\smartheap\smrtheap.h"
- #include "../game/q_shared.h"
- #include "..\qcommon\qcommon.h"
- #include <stdio.h>
- #include <map>
- using namespace std;
- #if MEM_DEBUG
- #include "..\smartheap\heapagnt.h"
- static const int maxStack=2048;
- static int TotalMem;
- static int TotalBlocks;
- static int nStack;
- static char StackNames[maxStack][256];
- static int StackSize[maxStack];
- static int StackCount[maxStack];
- static int StackCache[48];
- static int StackCacheAt=0;
- static int CheckpointSize[3000];
- static int CheckpointCount[3000];
- //#define _FASTRPT_
- #ifdef _FASTRPT_
- class CMyStrComparator
- {
- public:
- bool operator()(const char *s1, const char *s2) const { return(strcmp(s1, s2) < 0); }
- };
- hmap<const char *,int,CMyStrComparator> Lookup;
- #endif
- cvar_t *mem_leakfile;
- cvar_t *mem_leakreport;
- MEM_BOOL MEM_CALLBACK MyMemReporter2(MEM_ERROR_INFO *info)
- {
- static char buffer[10000];
- if (!info->objectCreationInfo)
- return 1;
- info=info->objectCreationInfo;
- int idx=info->checkpoint;
- if (idx<0||idx>=1000)
- {
- idx=0;
- }
- CheckpointCount[idx]++;
- CheckpointSize[idx]+=info->argSize;
- dbgMemFormatCall(info,buffer,9999);
- if (strstr(buffer,"ntdll"))
- return 1;
- if (strstr(buffer,"CLBCATQ"))
- return 1;
- int i;
- TotalBlocks++;
- if (TotalBlocks%1000==0)
- {
- char mess[1000];
- sprintf(mess,"%d blocks processed\n",TotalBlocks);
- OutputDebugString(mess);
- }
- for (i=strlen(buffer);i>0;i--)
- {
- if (buffer[i]=='\n')
- break;
- }
- if (!i)
- return 1;
- buffer[i]=0;
- char *buf=buffer;
- while (*buf)
- {
- if (*buf=='\n')
- {
- buf++;
- break;
- }
- buf++;
- }
- char *start=0;
- char *altName=0;
- while (*buf)
- {
- while (*buf==' ')
- buf++;
- start=buf;
- while (*buf!=0&&*buf!='\n')
- buf++;
- if (*start)
- {
- if (*buf)
- {
- *buf=0;
- buf++;
- }
- if (strlen(start)>255)
- start[255]=0;
- if (strstr(start,"std::"))
- {
- altName="std::??";
- // start=0;
- continue;
- }
- if (strstr(start,"Malloc"))
- {
- altName="Malloc??";
- start=0;
- continue;
- }
- if (strstr(start,"G_Alloc"))
- {
- altName="G_Alloc";
- start=0;
- continue;
- }
- if (strstr(start,"Hunk_Alloc"))
- {
- altName="Hunk_Alloc";
- start=0;
- continue;
- }
- if (strstr(start,"FS_LoadFile"))
- {
- altName="FS_LoadFile";
- start=0;
- continue;
- }
- if (strstr(start,"CopyString"))
- {
- altName="CopyString";
- start=0;
- continue;
- }
- break;
- }
- }
- if (!start||!*start)
- {
- start=altName;
- if (!start||!*start)
- {
- start="UNKNOWN";
- }
- }
- #ifdef _FASTRPT_
- hmap<const char *,int,CMyStrComparator>::iterator f=Lookup.find(start);
- if(f==Lookup.end())
- {
- strcpy(StackNames[nStack++],start);
- Lookup[(const char *)&StackNames[nStack-1]]=nStack-1;
- StackSize[nStack-1]=info->argSize;
- StackCount[nStack-1]=1;
- }
- else
- {
- StackSize[(*f).second]+=info->argSize;
- StackCount[(*f).second]++;
- }
- #else
- for (i=0;i<48;i++)
- {
- if (StackCache[i]<0||StackCache[i]>=nStack)
- continue;
- if (!strcmpi(start,StackNames[StackCache[i]]))
- break;
- }
- if (i<48)
- {
- StackSize[StackCache[i]]+=info->argSize;
- StackCount[StackCache[i]]++;
- }
- else
- {
- for (i=0;i<nStack;i++)
- {
- if (!strcmpi(start,StackNames[i]))
- break;
- }
- if (i<nStack)
- {
- StackSize[i]+=info->argSize;
- StackCount[i]++;
- StackCache[StackCacheAt]=i;
- StackCacheAt++;
- if (StackCacheAt>=48)
- StackCacheAt=0;
- }
- else if (i<maxStack)
- {
- strcpy(StackNames[i],start);
- StackSize[i]=info->argSize;
- StackCount[i]=1;
- nStack++;
- }
- else if (nStack<maxStack)
- {
- nStack++;
- strcpy(StackNames[maxStack-1],"*****OTHER*****");
- StackSize[maxStack-1]=info->argSize;
- StackCount[maxStack-1]=1;
- }
- else
- {
- StackSize[maxStack-1]+=info->argSize;
- StackCount[maxStack-1]++;
- }
- }
- #endif
- TotalMem+=info->argSize;
- return 1;
- }
- MEM_BOOL MEM_CALLBACK MyMemReporter3(MEM_ERROR_INFO *info)
- {
- static char buffer[10000];
- if (!info->objectCreationInfo)
- return 1;
- info=info->objectCreationInfo;
- int idx=info->checkpoint;
- if (idx<0||idx>=3000)
- {
- idx=0;
- }
- CheckpointCount[idx]++;
- CheckpointSize[idx]+=info->argSize;
- dbgMemFormatCall(info,buffer,9999);
- int i;
- TotalBlocks++;
- // if (TotalBlocks%1000==0)
- // {
- // char mess[1000];
- // sprintf(mess,"%d blocks processed\n",TotalBlocks);
- // OutputDebugString(mess);
- // }
- for (i=strlen(buffer);i>0;i--)
- {
- if (buffer[i]=='\n')
- break;
- }
- if (!i)
- return 1;
- buffer[i]=0;
- char *buf=buffer;
- while (*buf)
- {
- if (*buf=='\n')
- {
- buf++;
- break;
- }
- buf++;
- }
- char *start=0;
- char *altName=0;
- while (*buf)
- {
- while (*buf==' ')
- buf++;
- start=buf;
- while (*buf!=0&&*buf!='\n')
- buf++;
- if (*start)
- {
- if (*buf)
- {
- *buf=0;
- buf++;
- }
- if (strlen(start)>255)
- start[255]=0;
- if (strstr(start,"SV_AreaEntities"))
- {
- altName="SV_AreaEntities??";
- start=0;
- continue;
- }
- if (strstr(start,"SV_Trace"))
- {
- altName="SV_Trace??";
- start=0;
- continue;
- }
- if (strstr(start,"SV_PointContents"))
- {
- altName="SV_PointContents??";
- start=0;
- continue;
- }
- if (strstr(start,"CG_Trace"))
- {
- altName="??";
- start=0;
- continue;
- }
- if (strstr(start,"CG_PointContents"))
- {
- altName="??";
- start=0;
- continue;
- }
- /*
- if (strstr(start,""))
- {
- altName="??";
- start=0;
- continue;
- }
- if (strstr(start,""))
- {
- altName="??";
- start=0;
- continue;
- }
- */
- break;
- }
- }
- if (!start||!*start)
- {
- start=altName;
- if (!start||!*start)
- {
- start="UNKNOWN";
- }
- }
- #ifdef _FASTRPT_
- hmap<const char *,int,CMyStrComparator>::iterator f=Lookup.find(start);
- if(f==Lookup.end())
- {
- strcpy(StackNames[nStack++],start);
- Lookup[(const char *)&StackNames[nStack-1]]=nStack-1;
- StackSize[nStack-1]=info->argSize;
- StackCount[nStack-1]=1;
- }
- else
- {
- StackSize[(*f).second]+=info->argSize;
- StackCount[(*f).second]++;
- }
- #else
- for (i=0;i<48;i++)
- {
- if (StackCache[i]<0||StackCache[i]>=nStack)
- continue;
- if (!strcmpi(start,StackNames[StackCache[i]]))
- break;
- }
- if (i<48)
- {
- StackSize[StackCache[i]]+=info->argSize;
- StackCount[StackCache[i]]++;
- }
- else
- {
- for (i=0;i<nStack;i++)
- {
- if (!strcmpi(start,StackNames[i]))
- break;
- }
- if (i<nStack)
- {
- StackSize[i]+=info->argSize;
- StackCount[i]++;
- StackCache[StackCacheAt]=i;
- StackCacheAt++;
- if (StackCacheAt>=48)
- StackCacheAt=0;
- }
- else if (i<maxStack)
- {
- strcpy(StackNames[i],start);
- StackSize[i]=info->argSize;
- StackCount[i]=1;
- nStack++;
- }
- else if (nStack<maxStack)
- {
- nStack++;
- strcpy(StackNames[maxStack-1],"*****OTHER*****");
- StackSize[maxStack-1]=info->argSize;
- StackCount[maxStack-1]=1;
- }
- else
- {
- StackSize[maxStack-1]+=info->argSize;
- StackCount[maxStack-1]++;
- }
- }
- #endif
- TotalMem+=info->argSize;
- return 1;
- }
- void SH_Checking_f(void);
- #endif
- class Leakage
- {
- MEM_POOL MyPool;
- public:
- Leakage()
- {
- MyPool = MemInitDefaultPool();
- // MemPoolSetSmallBlockSize(MyPool, 16);
- MemPoolSetSmallBlockAllocator(MyPool,MEM_SMALL_BLOCK_SH3);
- #if MEM_DEBUG
- dbgMemSetGuardSize(2);
- EnableChecking(100000);
- #endif
- }
- void LeakReport(void)
- {
- #if MEM_DEBUG
- // This just makes sure we have map nodes available without allocation
- // during the heap walk (which could be bad).
- int i;
- #ifdef _FASTRPT_
- hlist<int> makeSureWeHaveNodes;
- for(i=0;i<5000;i++)
- {
- makeSureWeHaveNodes.push_back(0);
- }
- makeSureWeHaveNodes.clear();
- Lookup.clear();
- #endif
- char mess[1000];
- int blocks=dbgMemTotalCount();
- int mem=dbgMemTotalSize()/1024;
- sprintf(mess,"Final Memory Summary %d blocks %d K\n",blocks,mem);
- OutputDebugString(mess);
- for (i=0;i<3000;i++)
- {
- CheckpointSize[i]=0;
- CheckpointCount[i]=0;
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter2);
- dbgMemReportLeakage(NULL,1,1000);
- MemSetErrorHandler(MemDefaultErrorHandler);
- multimap<int,pair<int,char *> > sortit;
- multimap<int,pair<int,char *> >::iterator j;
- if (TotalBlocks)
- {
- // Sort by size.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("**********Memory Leak Report**********\n");
- OutputDebugString("*************** By Size **************\n");
- OutputDebugString("**************************************\n");
- sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
- OutputDebugString(mess);
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackSize[i],pair<int,char *>(StackCount[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%5d KB %6d cnt %s\n",-(*j).first/1024,(*j).second.first,(*j).second.second);
- // if (!(-(*j).first/1024))
- // break;
- Sleep(5);
- OutputDebugString(mess);
- }
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("**********Memory Leak Report**********\n");
- OutputDebugString("************** By Count **************\n");
- OutputDebugString("**************************************\n");
- sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
- OutputDebugString(mess);
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%5d KB %6d cnt %s\n",(*j).second.first/1024,-(*j).first,(*j).second.second);
- // if (!(-(*j).first/1024))
- // break;
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- else
- {
- OutputDebugString("No Memory Leaks\n");
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter3);
- dbgMemReportLeakage(NULL,2001,2001);
- MemSetErrorHandler(MemDefaultErrorHandler);
- if (TotalBlocks)
- {
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("SV_PointContents ");
- sprintf(mess,"%d Calls.\n",TotalBlocks);
- OutputDebugString(mess);
- OutputDebugString("**************************************\n");
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter3);
- dbgMemReportLeakage(NULL,2002,2002);
- MemSetErrorHandler(MemDefaultErrorHandler);
- if (TotalBlocks)
- {
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("SV_Trace ");
- sprintf(mess,"%d Calls.\n",TotalBlocks);
- OutputDebugString(mess);
- OutputDebugString("**************************************\n");
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter3);
- dbgMemReportLeakage(NULL,2003,2003);
- MemSetErrorHandler(MemDefaultErrorHandler);
- if (TotalBlocks)
- {
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("SV_AreaEntities ");
- sprintf(mess,"%d Calls.\n",TotalBlocks);
- OutputDebugString(mess);
- OutputDebugString("**************************************\n");
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter3);
- dbgMemReportLeakage(NULL,2004,2004);
- MemSetErrorHandler(MemDefaultErrorHandler);
- if (TotalBlocks)
- {
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("CG_Trace ");
- sprintf(mess,"%d Calls.\n",TotalBlocks);
- OutputDebugString(mess);
- OutputDebugString("**************************************\n");
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- TotalMem=0;
- TotalBlocks=0;
- nStack=0;
- MemSetErrorHandler(MyMemReporter3);
- dbgMemReportLeakage(NULL,2005,2005);
- MemSetErrorHandler(MemDefaultErrorHandler);
- if (TotalBlocks)
- {
- // Sort by count.
- Sleep(100);
- OutputDebugString("**************************************\n");
- OutputDebugString("CG_PointContents ");
- sprintf(mess,"%d Calls.\n",TotalBlocks);
- OutputDebugString(mess);
- OutputDebugString("**************************************\n");
- sortit.clear();
- for (i=0;i<nStack;i++)
- sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
- Sleep(5);
- for (j=sortit.begin();j!=sortit.end();j++)
- {
- sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
- Sleep(5);
- OutputDebugString(mess);
- }
- }
- #if 0 //sw doesn't have the tag stuff
- // Sort by size.
- Sleep(5);
- OutputDebugString("***************************************\n");
- OutputDebugString("By Tag, sort: size ********************\n");
- OutputDebugString("size(K) count name \n");
- OutputDebugString("-----------------------\n");
- Sleep(5);
- multimap<int,int> sorted;
- for (i=0;i<1000;i++)
- {
- if (CheckpointCount[i])
- {
- sorted.insert(pair<int,int>(-CheckpointSize[i],i));
- }
- }
- multimap<int,int>::iterator k;
- for (k=sorted.begin();k!=sorted.end();k++)
- {
- sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
- Sleep(5);
- OutputDebugString(mess);
- }
-
- // Sort by count.
- Sleep(5);
- OutputDebugString("By Tag, sort: count *******************\n");
- OutputDebugString("size(K) count name \n");
- OutputDebugString("-----------------------\n");
- Sleep(5);
- sorted.clear();
- for (i=0;i<1000;i++)
- {
- if (CheckpointCount[i])
- {
- sorted.insert(pair<int,int>(-CheckpointCount[i],i));
- }
- }
- for (k=sorted.begin();k!=sorted.end();k++)
- {
- sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
- Sleep(5);
- OutputDebugString(mess);
- }
- #endif
- #endif
- }
- ~Leakage()
- {
- #if MEM_DEBUG
- if (mem_leakfile && mem_leakfile->integer)
- {
- dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_FILE,"leakage.out");
- dbgMemReportLeakage(NULL,1,1);
- dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_PROMPT,NULL);
- }
- if (mem_leakreport && mem_leakreport->integer)
- {
- LeakReport();
- }
- #endif
- }
- #if MEM_DEBUG
- void EnableChecking(int x)
- {
- if (x)
- {
- dbgMemSetSafetyLevel(MEM_SAFETY_DEBUG);
- dbgMemPoolSetCheckFrequency(MyPool, x);
- dbgMemSetCheckFrequency(x);
- dbgMemDeferFreeing(TRUE);
- dbgMemSetDeferQueueLen(50000);
- }
- else
- {
- dbgMemSetSafetyLevel(MEM_SAFETY_SOME);
- dbgMemDeferFreeing(FALSE);
- }
- }
- #endif
- };
- static Leakage TheLeakage;
- #if MEM_DEBUG
- void MEM_Checking_f(void)
- {
- if (Cmd_Argc() != 2)
- {
- Com_Printf ("mem_checking <frequency>\n");
- return;
- }
- if (atol(Cmd_Argv(1)) > 0 && atol(Cmd_Argv(1)) < 100)
- {
- Com_Printf ("mem_checking frequency is too low ( < 100 )\n");
- return;
- }
- TheLeakage.EnableChecking(atol(Cmd_Argv(1)));
- }
- void MEM_Report_f(void)
- {
- if (0)
- {
- dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_FILE,"leakage.out");
- dbgMemReportLeakage(NULL,1,1);
- dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_PROMPT,NULL);
- }
- TheLeakage.LeakReport();
- }
- /*
- void myexit(void)
- {
- TheLeakage.LeakReport();
- }
- */
- void SH_Register(void)
- {
- Cmd_AddCommand ("mem_checking", MEM_Checking_f);
- Cmd_AddCommand ("mem_report", MEM_Report_f);
- mem_leakfile = Cvar_Get( "mem_leakfile", "0", 0 );
- mem_leakreport = Cvar_Get( "mem_leakreport", "1", 0 );
- // atexit(myexit);
- }
- #endif
|