00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00040 #include "PreCompiled.h"
00041
00042 #ifndef _PreComp_
00043 # ifdef _MSC_VER
00044 # include <cstdio>
00045 # include <time.h>
00046 # include <windows.h>
00047 # include <crtdbg.h>
00048 # endif
00049 #endif
00050
00051
00053 #include "MemDebug.h"
00054
00055 using namespace Base;
00056
00057 #if defined(_MSC_VER)
00058
00059
00072 class MemDebug
00073 {
00074 public:
00076 MemDebug();
00078 virtual ~MemDebug();
00079
00080 protected:
00081 static FILE *logFile;
00082
00085 static void __cdecl sDumpClientHook(void * pUserData, size_t nBytes);
00086 static int __cdecl sAllocHook(int nAllocType, void* pvData, size_t nSize,int nBlockUse,long lRequest,const unsigned char * szFileName,int nLine);
00087 static int sReportHook(int nRptType,char *szMsg,int *retVal);
00089 };
00090
00091
00092 #ifdef MemDebugOn
00093 MemDebug cSingelton;
00094 #endif
00095
00096
00097 #define SET_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
00098 #define CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
00099
00100 FILE *MemDebug::logFile = NULL;
00101
00102
00103
00104
00105
00106 MemDebug::MemDebug()
00107 {
00108
00109 char timeStr[15], dateStr[15];
00110
00111
00112
00113 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE );
00114 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR );
00115 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE );
00116 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR );
00117 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE );
00118 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR );
00119
00120
00121
00122 SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF | _CRTDBG_DELAY_FREE_MEM_DF );
00123
00124
00125 if ( logFile != NULL )
00126 throw "Base::MemDebug::MemDebug():38: Dont call the constructor by your self!";
00127 #if (_MSC_VER >= 1400)
00128 fopen_s( &logFile, "MemLog.txt", "w" );
00129 if ( logFile == NULL )
00130 throw "Base::MemDebug::MemDebug():41: File IO Error. Canot open log file...";
00131 _strtime_s( timeStr, 15 );
00132 _strdate_s( dateStr, 15 );
00133 #elif (_MSC_VER >= 1200)
00134 logFile = fopen( "MemLog.txt", "w" );
00135 if ( logFile == NULL )
00136 throw "Base::MemDebug::MemDebug():41: File IO Error. Canot open log file...";
00137 _strtime( timeStr );
00138 _strdate( dateStr );
00139 #endif
00140 fprintf( logFile,
00141 "Memory Allocation Log File for FreeCAD, run at %s on %s.\n",
00142 timeStr, dateStr );
00143 fputs( "-------------------------------------------------------------------\n", logFile );
00144
00145
00146 _CrtSetDumpClient( sDumpClientHook );
00147 _CrtSetAllocHook( sAllocHook );
00148 _CrtSetReportHook( sReportHook );
00149
00150 }
00151
00152 MemDebug::~MemDebug()
00153 {
00154 _CrtMemDumpAllObjectsSince( NULL );
00155
00156
00157
00158 fflush( logFile );
00159 fclose( logFile );
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 int MemDebug::sReportHook(int nRptType,char *szMsg,int *retVal)
00178 {
00179 char *RptTypes[] = { "Warning", "Error", "Assert" };
00180
00181 if ( ( nRptType > 0 ) || ( strstr( szMsg, "HEAP CORRUPTION DETECTED" ) ) )
00182 fprintf( logFile, "%s: %s", RptTypes[nRptType], szMsg );
00183
00184 retVal = 0;
00185
00186 return( 7 );
00187 }
00188
00189
00190
00191
00192
00193
00194 int __cdecl MemDebug::sAllocHook(
00195 int nAllocType,
00196 void * pvData,
00197 size_t nSize,
00198 int nBlockUse,
00199 long lRequest,
00200 const unsigned char * szFileName,
00201 int nLine
00202 )
00203 {
00204 char *operation[] = { " :", "Alloc :", "Realloc:", "Free :" };
00205 char *blockType[] = { "Free", "Normal", "CRT", "Ignore", "Client" };
00206
00207 if ( nBlockUse == _CRT_BLOCK )
00208 return( 7 );
00209
00210 _ASSERT( ( nAllocType > 0 ) && ( nAllocType < 4 ) );
00211 _ASSERT( ( nBlockUse >= 0 ) && ( nBlockUse < 5 ) );
00212
00213 if( nBlockUse !=4 )
00214 return(7);
00215
00216 fprintf( logFile,
00217 "%s (#%7d) %12ld byte (%s) in %s line %d",
00218 operation[nAllocType],lRequest, nSize, blockType[nBlockUse],szFileName, nLine);
00219 if ( pvData != NULL )
00220 fprintf( logFile, " at %p\n", pvData );
00221 else
00222 fprintf( logFile, "\n", pvData );
00223
00224 return( 7 );
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 void __cdecl MemDebug::sDumpClientHook(
00236 void * pUserData,
00237 size_t nBytes
00238 )
00239 {
00240 long requestNumber=0;
00241 _CrtIsMemoryBlock(pUserData,(unsigned int)nBytes,&requestNumber,NULL,NULL);
00242 fprintf( logFile, "Leak : (#%7d) %12ld bytes (%p) \n", requestNumber, nBytes, pUserData );
00243
00244 }
00245
00246
00247
00248 MemCheck::MemCheck()
00249 {
00250
00251 _CrtMemCheckpoint( &s1 );
00252 }
00253
00254 MemCheck::~MemCheck()
00255 {
00256
00257 _CrtMemCheckpoint( &s2 );
00258 if ( _CrtMemDifference( &s3, &s1, &s2 ) )
00259 _CrtMemDumpStatistics( &s3 );
00260 }
00261
00262 void MemCheck::setNextCheckpoint()
00263 {
00264
00265 _CrtMemCheckpoint( &s2 );
00266 if ( _CrtMemDifference( &s3, &s1, &s2 ) )
00267 _CrtMemDumpStatistics( &s3 );
00268
00269
00270 _CrtMemCheckpoint( &s1 );
00271 }
00272
00273 bool MemCheck::checkMemory()
00274 {
00275 return _CrtCheckMemory() ? true : false;
00276 }
00277
00278 bool MemCheck::dumpLeaks()
00279 {
00280 return _CrtDumpMemoryLeaks() ? true : false;
00281 }
00282
00283 bool MemCheck::isValidHeapPointer(const void* userData)
00284 {
00285 return _CrtIsValidHeapPointer(userData) ? true : false;
00286 }
00287
00288 #endif