Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

memorycheck.cpp

Go to the documentation of this file.
00001 
00008 /***************************************************************************
00009                           memorycheck.cpp  -  description
00010                              -------------------
00011     begin                : Wed Nov 29 2000
00012     copyright            : (C) 2000 by Martin Bickel
00013     email                : bickel@asc-hq.org
00014  ***************************************************************************/
00015 
00016 /***************************************************************************
00017  *                                                                         *
00018  *   This program is free software; you can redistribute it and/or modify  *
00019  *   it under the terms of the GNU General Public License as published by  *
00020  *   the Free Software Foundation; either version 2 of the License, or     *
00021  *   (at your option) any later version.                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 
00026 #ifdef MEMCHK
00027 
00028   int blockNum = 0;
00029   int operationID = 0;
00030   int errorNum = 0;
00031   int breakOnFree = 0;
00032   const int infoblocksize = 3;
00033 
00034   bool memchk_initialized = false;
00035 
00036 
00037   bool memchk_reallyComplete = false;  // this variable is intended to be set by the debugger
00038   int memchk_breakOnOp = -1;           // this variable is intended to be set by the debugger
00039 
00040   void memchkError ( )
00041   {
00042      errorNum++;
00043      fprintf(stderr, "memchkError !\n");
00044   }
00045 
00046   class Block {
00047      public:
00048         int start;
00049         int stop;
00050         int userStart;
00051         int size;
00052         int allocated;
00053         int freed;
00054         int allocatedOP;
00055         int freedOP;
00056   };
00057 
00058 
00059   Block blocks[1000000];
00060 
00061   void* verifyblock ( int tp, Block* b )
00062   {
00063      int error = 0;
00064      int* tmpi = (int*) b->start;
00065 
00066      if ( tp != -1 )
00067         if ( tmpi[0] != tp )
00068            error++;  // for example: allocated with new  ; freed with delete[]
00069 /*
00070      if ( tmpi[1] != (int) tmpi) {
00071         memchkError();
00072         #ifdef logging
00073          logtofile ( "memory check: verifyblock : error A at address %x", p );
00074         #endif
00075      }
00076 */
00077      int amt = tmpi[2];
00078 
00079      for ( int i = 0; i < 25; i++ ) {
00080         if ( tmpi[infoblocksize + i] != 0x12345678) {
00081            memchkError();
00082            #ifdef logging
00083             logtofile ( "memory check: verifyblock : error C at address %x", p );
00084            #endif
00085         }
00086 
00087         if ( tmpi[infoblocksize + i + (amt+3)/4 + 25] != 0x87654321 ) {
00088            memchkError();
00089            #ifdef logging
00090             logtofile ( "memory check: verifyblock : error D at address %x", p );
00091            #endif
00092         }
00093      }
00094      return tmpi;
00095   }
00096 
00097   void verifyallblocks ( void )
00098   {
00099      for ( int i = 0; i < blockNum; i++ )
00100         if ( !blocks[i].freed )
00101            verifyblock ( -1, &blocks[i] );
00102   }
00103 
00104   void* memchkAlloc ( int tp, size_t amt )
00105   {
00106      if ( ! memchk_initialized ) {
00107         memset ( blocks, 0, sizeof ( blocks ));
00108         memchk_initialized = true;
00109      }
00110 
00111      if ( memchk_reallyComplete )
00112         verifyallblocks();
00113 
00114      Block& b = blocks[ blockNum++ ];
00115      if ( blockNum >= 1000000 )
00116         memchkError();
00117 
00118      b.size = amt + (50+infoblocksize) * 4;
00119      b.allocated++;
00120 
00121      if ( operationID == memchk_breakOnOp )
00122         memchkError();
00123 
00124      b.allocatedOP = operationID++;
00125 
00126      void* tmp = malloc ( b.size+4 );
00127 
00128 
00129      b.start = (int) tmp;
00130      b.stop = b.start + b.size;
00131 
00132      for ( int i = 0; i < blockNum-1; i++ ) {
00133         if ( !blocks[i].freed ) {
00134            if ( b.start >= blocks[i].start && b.start < blocks[i].stop )
00135               memchkError();
00136            if ( b.stop >= blocks[i].start  && b.stop < blocks[i].stop )
00137               memchkError();
00138            if ( blocks[i].start < b.start && blocks[i].stop > b.stop )
00139               memchkError();
00140         }
00141      }
00142 
00143 
00144      int* tmpi = (int*) tmp;
00145      /*
00146      if ( (int) tmpi == 0x1bb2138 || (int) tmpi == 0x1bcf178 )
00147         error++;
00148         */
00149      tmpi[0] = tp;
00150 
00151      if ( 4 < infoblocksize )
00152        tmpi[4] = (int) tmp;
00153 
00154      if ( 2 < infoblocksize )
00155        tmpi[2] = amt;
00156 
00157      if ( 3 < infoblocksize )
00158         tmpi[3] = b.allocatedOP;
00159 
00160      if ( 1 < infoblocksize )
00161         tmpi[1] = blockNum-1;
00162 
00163      for ( int i = 0; i < 25; i++ ) {
00164         tmpi[infoblocksize + i] = 0x12345678;
00165         tmpi[infoblocksize + i + (amt+3)/4 + 25] = 0x87654321;
00166      }
00167      void* p = &tmpi[25+infoblocksize];
00168      b.userStart = (int) p;
00169      return p;
00170   }
00171 
00172   void memchkFree ( int tp, void* buf )
00173   {
00174      if ( breakOnFree == (int) buf )
00175         memchkError();
00176 
00177      Block* b = NULL;
00178      for ( int i = blockNum-1; i>= 0 ; i-- )
00179         if ( blocks[i].userStart == (int) buf ) {
00180            b = &blocks[i];
00181            break;
00182         }
00183 
00184      if ( b ) {
00185 
00186         if ( memchk_reallyComplete )
00187            verifyallblocks();
00188 
00189         void* tmpi = verifyblock ( tp, b );
00190 
00191         if ( b->freed > 0 )
00192            memchkError();
00193 
00194         if ( b->allocated <= 0 )
00195            memchkError();
00196 
00197         if ( operationID == memchk_breakOnOp )
00198            memchkError();
00199 
00200 
00201         b->freed++;
00202         b->freedOP = operationID++;
00203 
00204         free ( tmpi );
00205      } else
00206         free ( buf );
00207   }
00208 
00209 
00210 
00211 
00212 
00213   void *operator new( size_t amt )
00214   {
00215       return( memchkAlloc( 100, amt ) );
00216   }
00217 
00218   void operator delete( void *p )
00219   {
00220      if ( p )
00221       memchkFree( 100, p );
00222   }
00223 
00224   void *operator new []( size_t amt )
00225   {
00226       return( memchkAlloc( 102, amt ) );
00227   }
00228 
00229   void operator delete []( void *p )
00230   {
00231      if ( p )
00232       memchkFree( 102, p );
00233   }
00234 
00235   void* asc_malloc ( size_t size )
00236   {
00237      void* tmp = memchkAlloc ( 104, size );
00238      return tmp;
00239   }
00240 
00241   void asc_free ( void* p )
00242   {
00243      memchkFree ( 104, p );
00244   }
00245 
00246 #else
00247 
00248   void* asc_malloc ( size_t size )
00249   {
00250      void* tmp = malloc ( size );
00251     #ifdef _DOS_
00252      if ( tmp == NULL )
00253         new_new_handler();
00254     #else
00255      if ( tmp == NULL )
00256         fatalError("Out of memory!");
00257     #endif
00258      return tmp;
00259   }
00260 
00261   void asc_free ( void* p )
00262   {
00263      free ( p );
00264   }
00265 
00266 
00267 #endif

Generated on Tue Jun 24 01:27:45 2008 for Advanced Strategic Command by  doxygen 1.4.2