home *** CD-ROM | disk | FTP | other *** search
/ Game.EXE 2002 May / Game.EXE_05_2002.iso / Alawar / Lib / safe_new.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-08  |  4.9 KB  |  225 lines

  1. #include "safe_new.h"
  2.  
  3. #ifdef SAFE_NEW
  4.  
  5. #undef new
  6. #undef delete
  7.  
  8. #include <win32/windows.h> // For HFILE
  9. #include <memory>
  10. #include <SimpleList.h>
  11.  
  12. struct MemNode : public SimpleListNode<MemNode>
  13. {
  14.     static const unsigned nice_crc;
  15.  
  16.     const char * file;
  17.     unsigned line;
  18.     unsigned size;
  19.     unsigned crc;
  20.  
  21.     bool test_validity()
  22.     {
  23.         unsigned fint = reinterpret_cast<unsigned>( file );
  24.         return (line + size + fint + crc) == nice_crc;
  25.     }
  26.     void make_valid()
  27.     {
  28.         unsigned fint = reinterpret_cast<unsigned>( file );
  29.         crc = nice_crc - (line + size + fint);
  30.     }
  31.     void make_invalid()
  32.     {
  33.         unsigned fint = reinterpret_cast<unsigned>( file );
  34.         crc = (line + size + fint);
  35.     }
  36. };
  37. const unsigned MemNode::nice_crc = ('N' << 24) + ('i' << 16) + ('c' << 8) + 'e';
  38.  
  39. static MemNode * start;
  40. static char * start_place[ sizeof(MemNode) ];
  41.  
  42. static int simple_counter = 0;
  43.  
  44. class RepFile
  45. {
  46.     HANDLE hfile;
  47. public:
  48.     explicit RepFile(bool create)
  49.     {
  50.         hfile = CreateFile( "memory.log", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL );
  51.         if( hfile != INVALID_HANDLE_VALUE && !create )
  52.         {
  53.             SetFilePointer( hfile, 0, NULL, FILE_END );
  54.         }
  55.     }
  56.     ~RepFile()
  57.     {
  58.         if( hfile != INVALID_HANDLE_VALUE )
  59.             CloseHandle( hfile );
  60.     }
  61.     void write( const char * str )const
  62.     {
  63.         if( hfile == INVALID_HANDLE_VALUE )
  64.             return;
  65.         DWORD read = 0;
  66.         WriteFile( hfile, str, strlen(str), &read, NULL );
  67.     }
  68. };
  69.  
  70. int MemoryLeakReporterCreator::ref_count = 0;
  71.  
  72. MemoryLeakReporterCreator::MemoryLeakReporterCreator()
  73. {
  74.     if( ++ref_count == 1 )
  75.     {
  76.     }
  77. }
  78.  
  79. MemoryLeakReporterCreator::~MemoryLeakReporterCreator()
  80. {
  81.     if( --ref_count == 0 )
  82.     {
  83.         MemNode * curr = start->get_next();
  84.  
  85.         RepFile rep_file( false );
  86.         rep_file.write( "Memory leaks:\n    addr |    size | line | file\n---------+---------+------+----------\n" );
  87.         for( ; curr ; curr = curr->get_next() )
  88.         {
  89.             char buff[1024];
  90.             int bs = wsprintf( buff,"%8X |%8d |%5d | %s\n", reinterpret_cast<unsigned>( curr ), curr->size, curr->line, curr->file );
  91.             rep_file.write( buff );
  92.         }
  93.     }
  94. }
  95.  
  96.  
  97. static void * our_alloc( size_t s, const char * file, int line )
  98. {
  99.     void * mama = malloc( s + sizeof(MemNode) );
  100.     if( mama == 0 )
  101.     {
  102.         throw std::bad_alloc();
  103.     }
  104.     if( !start )
  105.     {
  106.         start = new(start_place) MemNode;
  107.         RepFile rep_file( true );
  108.         rep_file.write( "Twice deleted:\n    addr |    size | line | file\n---------+---------+------+----------\n" );
  109.     }
  110.     ++simple_counter;
  111.  
  112.     char * chama = (char *)mama;
  113.     MemNode * just = new(mama) MemNode; // in-place new
  114.     if( just == (void *)0x00851AD0 )
  115.         just = just;
  116.  
  117.     just->file = file;
  118.     just->line = line;
  119.     just->size = s;
  120.     just->make_valid();
  121.  
  122.     just->link( start );
  123.  
  124.     void * p = (void *)( chama + sizeof(MemNode) );
  125.     return p;
  126. }
  127.  
  128. static const char * CurrentFile = 0;
  129. static int CurrentLine = 0;
  130.  
  131. void memory_leak_report_delete( const char * cf, int cl )
  132. {
  133.     CurrentFile = cf;
  134.     CurrentLine = cl;
  135. }
  136.  
  137. static void report_bad_delete( unsigned addr, unsigned size, unsigned line, const char * file )
  138. {
  139.     RepFile rep_file( false );
  140.     char buff[1024];
  141.     int bs = wsprintf( buff,"%8X |%8d |%5d | %s\n", addr, size, line, file );
  142.     rep_file.write( buff );
  143.     bs = wsprintf( buff,"               In: |%5d | %s\n", CurrentLine, CurrentFile );
  144.     rep_file.write( buff );
  145. }
  146.  
  147. static void our_free( void * p, const char * file, int line )
  148. {
  149.     if( p == 0 )
  150.     {
  151.         CurrentFile = 0;
  152.         CurrentLine = 0;
  153.         return;
  154.     }
  155.     char * chama = (char *)p - sizeof(MemNode);
  156.     void * mama = chama;
  157.     MemNode * just = (MemNode *)mama;
  158.  
  159.     try
  160.     {
  161.         if( !just->test_validity() )
  162.         {
  163.             report_bad_delete( reinterpret_cast<unsigned>( p ), just->size, just->line, just->file );
  164.             CurrentFile = 0;
  165.             CurrentLine = 0;
  166.             return;
  167.         }
  168.         just->make_invalid();
  169.         just->unlink();
  170.  
  171.         free( mama );
  172.     }
  173.     catch(...) // Invalid address dereference, really
  174.     {
  175.         report_bad_delete( reinterpret_cast<unsigned>( p ), 0, 0, "Exception occured, trying to delete the memory at this address");
  176.         CurrentFile = 0;
  177.         CurrentLine = 0;
  178.         return;
  179.     }
  180.     CurrentFile = 0;
  181.     CurrentLine = 0;
  182.     --simple_counter;
  183. }
  184.  
  185. void * __cdecl operator new( size_t s, const char * file, int line )
  186. {
  187.     return our_alloc( s, file, line );
  188. }
  189.  
  190. void __cdecl operator delete( void * p, const char * file, int line )
  191. {
  192.     our_free( p, file, line );
  193. }
  194.  
  195. void * __cdecl operator new( size_t s )
  196. {
  197.     return operator new( s, "Runtime", 0 );
  198. }
  199.  
  200. void __cdecl operator delete( void * p )
  201. {
  202.     operator delete( p, "Runtime", 0 );
  203. }
  204.  
  205. void * __cdecl operator new[]( size_t s )
  206. {
  207.     return operator new( s );
  208. }
  209.  
  210. void __cdecl operator delete[]( void * p )
  211. {
  212.     operator delete( p );
  213. }
  214.  
  215. void * __cdecl operator new[]( size_t s, const char * file, int line )
  216. {
  217.     return operator new( s, file, line );
  218. }
  219.  
  220. void __cdecl operator delete[]( void * p, const char * file, int line )
  221. {
  222.     operator delete( p, file, line );
  223. }
  224.  
  225. #endif