MemDebug.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   (c) Jürgen Riegel (juergen.riegel@web.de) 2006                        *   
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU Library General Public License (LGPL)   *
00008  *   as published by the Free Software Foundation; either version 2 of     *
00009  *   the License, or (at your option) any later version.                   *
00010  *   for detail see the LICENCE text file.                                 *
00011  *                                                                         *
00012  *   FreeCAD is distributed in the hope that it will be useful,            *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with FreeCAD; if not, write to the Free Software        * 
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020  *   USA                                                                   *
00021  *                                                                         *
00022  *   Juergen Riegel 2006                                                   *
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 // the one and only MemDebug instance. 
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 // Construction/Destruction
00104 
00105 
00106 MemDebug::MemDebug()
00107 {
00108    //_CrtMemState checkPt1;
00109    char timeStr[15], dateStr[15];         // Used to set up log file
00110 
00111 
00112    // Send all reports to STDOUT, since this example is a console app
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    // Set the debug heap to report memory leaks when the process terminates,
00121    // and to keep freed blocks in the linked list.
00122    SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF | _CRTDBG_DELAY_FREE_MEM_DF );
00123 
00124    // Open a log file for the hook functions to use 
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    // Install the hook functions
00146    _CrtSetDumpClient( sDumpClientHook );
00147    _CrtSetAllocHook( sAllocHook );
00148    _CrtSetReportHook( sReportHook );
00149 
00150 }
00151 
00152 MemDebug::~MemDebug()
00153 {
00154   _CrtMemDumpAllObjectsSince( NULL );
00155   //_CrtCheckMemory( );
00156 
00157   // This fflush needs to be removed...
00158   fflush( logFile );
00159   fclose( logFile );
00160 }
00161 
00162 
00163 //**************************************************************************
00164 // separator for other implemetation aspects
00165 
00166 
00167 /* REPORT HOOK FUNCTION
00168    --------------------
00169    Again, report hook functions can serve a very wide variety of purposes.
00170    This one logs error and assertion failure debug reports in the
00171    log file, along with 'Damage' reports about overwritten memory.
00172 
00173    By setting the retVal parameter to zero, we are instructing _CrtDbgReport
00174    to return zero, which causes execution to continue. If we want the function
00175    to start the debugger, we should have _CrtDbgReport return one.
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 );         // Allow the report to be made as usual (True = 7, False = 0)
00187 }
00188 
00189 /* ALLOCATION HOOK FUNCTION
00190    -------------------------
00191    An allocation hook function can have many, many different
00192    uses. This one simply logs each allocation operation in a file.
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 )   // Ignore internal C runtime library allocations
00208       return( 7 ); // (True = 7, False = 0)
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 );         // Allow the memory operation to proceed (True = 7, False = 0)
00225 }
00226 
00227 
00228 /* CLIENT DUMP HOOK FUNCTION
00229    -------------------------
00230    A hook function for dumping a Client block usually reports some
00231    or all of the contents of the block in question.  The function
00232    below also checks the data in several ways, and reports corruption
00233    or inconsistency as an assertion failure.
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     // Store a memory checkpoint in the s1 memory-state structure
00251     _CrtMemCheckpoint( &s1 );
00252 }
00253 
00254 MemCheck::~MemCheck()
00255 {
00256     // Store a 2nd memory checkpoint in s2
00257     _CrtMemCheckpoint( &s2 );
00258     if ( _CrtMemDifference( &s3, &s1, &s2 ) )
00259         _CrtMemDumpStatistics( &s3 );
00260 }
00261 
00262 void MemCheck::setNextCheckpoint()
00263 {
00264     // Store a 2nd memory checkpoint in s2
00265     _CrtMemCheckpoint( &s2 );
00266     if ( _CrtMemDifference( &s3, &s1, &s2 ) )
00267         _CrtMemDumpStatistics( &s3 );
00268 
00269     // Store a memory checkpoint in the s1 memory-state structure
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

Generated on Wed Nov 23 19:00:22 2011 for FreeCAD by  doxygen 1.6.1