C++重载新问题

问题描述:

我已经取代了常规的新操作符。 基本上我们分配一个内存池(比如16mb),当新的被调用的时候,返回 一个偏移量,直到没有空间再增加一个池为止。只有当该池中的所有元素都被释放后,池 才会被删除。C++重载新问题

我测试过这个类,它的效果很好,比原来的新版本快8-15倍。 然而,有一个问题:我将它合并到我的其他大小很大的项目中,除了内存使用量增长非常快之外,它 正常工作。基本上池没有被释放,因为 他们的一些项目根本不被删除。此外,还有很多来自STL容器 的新(0),我不知道该如何回应。

下面是代码:

namespace rt 
{ 
     class pool 
     { 
      friend class alloc; 
      private: 
        unsigned int _numRecords; 
        unsigned int _sizeLeft; 
        char*  _ptr; 
        char*  _data; 


     }; 


     class alloc 
     { 
      public: 
        alloc(); 

        alloc(int mb); 

        ~alloc(); 

        void* allocate(unsigned int size); 

        void constructPool(unsigned int idx); 

        void destroyPool(unsigned int idx); 

        void deallocate(void* ptr); 

      private: 
        const static unsigned int   _numPools = 256; 
        const static unsigned int   _poolSize = 15*1024*1024; 
        const static unsigned int   _poolReplaceBound = 1*1024*1024; // if 1mb or less left we can replace it 
        pool*        _pools[_numPools]; 
        unsigned int      _curPoolIdx; 


     };   

这就是报头。 这里是实现:

namespace rt 
{ 
      class pool 
      { 
       friend class alloc; 
       private: 
         unsigned int _numRecords; 
         unsigned int _sizeLeft; 
         char*  _ptr; 
         char*  _data; 

      }; 


     class alloc 
     { 
      public: 
        alloc(); 

        alloc(int mb); 

        ~alloc(); 

        void* allocate(unsigned int size); 

        void constructPool(unsigned int idx); 

        void destroyPool(unsigned int idx); 

        void deallocate(void* ptr); 

      private: 
        const static unsigned int   _numPools = 256; 
        const static unsigned int   _poolSize = 15*1024*1024; 
        const static unsigned int   _poolReplaceBound = 1*1024*1024; // if 1mb or less left we can replace it 
        pool*        _pools[_numPools]; 
        unsigned int      _curPoolIdx; 


     };   

     extern alloc default_allocator; 
} 


#define RT_SAFE_MEM 
namespace rt 
{ 
     alloc default_allocator; 


     alloc::alloc() 
     { 
        for(int i = 0; i < _numPools; i++) _pools[i] = NULL; 
        _curPoolIdx = 0; 
        constructPool(_curPoolIdx); 
     } 

     alloc::~alloc() 
     { 

     } 

     void alloc::constructPool(unsigned int idx) 
     { 
            _pools[idx] = (pool*)malloc(sizeof(pool)); 
            _pools[idx]->_numRecords = 0; 
            _pools[idx]->_sizeLeft = _poolSize; 
            _pools[idx]->_data = (char*)calloc(_poolSize, 1); 

            _pools[idx]->_ptr = _pools[idx]->_data; 
     } 

     void alloc::destroyPool(unsigned int idx) 
     { 
      free(_pools[idx]->_data); 
      free(_pools[idx]); 
      _pools[idx] = NULL; 
     } 

     void* alloc::allocate(unsigned int size) 
     { 
      if(size == 0) 
      { 
        return NULL; 
      } 
      #ifdef RT_SAFE_MEM 

            if(size > _poolSize) 
            { 
              MessageBox(NULL, "Allocation size exceeded maximum.", "Executor", MB_OK); 
              return NULL; 
            } 
            if(*(_pools[_curPoolIdx]->_ptr) != 0) 
            { 
                    //leak 
                    unsigned int leaksize = strlen(_pools[_curPoolIdx]->_ptr); 
                    char str[50]; 
                    sprintf(str, "Memory corruption detected: wrote extra %u bytes. \nExporting to corrupt.txt", leaksize); 
                    FILE* fp = fopen("corrupt.txt", "w"); 
                    fwrite(_pools[_curPoolIdx]->_ptr, 1, leaksize, fp); 
                    fclose(fp); 
                    MessageBox(NULL, str, "Executor", MB_OK); 
                    return NULL; 
            } 

      #endif 

      if(_pools[_curPoolIdx]->_sizeLeft <= size) 
      { 
               //not enough size in this pool 
               //make a new one 
               _curPoolIdx++; 
               //printf("expand"); 
               constructPool(_curPoolIdx); 
               return allocate(size); 

      } 
      else 
      { 
       void* ans = (void*)_pools[_curPoolIdx]->_ptr; 
       _pools[_curPoolIdx]->_ptr+=size; 
       _pools[_curPoolIdx]->_sizeLeft-=size; 
       _pools[_curPoolIdx]->_numRecords++; 
       return ans; 
      } 
     } 


     void alloc::deallocate(void* ptr) 
     { 
      for(int i = 0; i <= _curPoolIdx; i++) 
      { 
        if(ptr >= _pools[i]->_data && ptr < _pools[i]->_ptr) 
        { 
          //pool i contains this object 
          //printf("found %d\n", i); 
          _pools[i]->_numRecords--; 
          if(_pools[i]->_numRecords == 0 && _pools[i]->_sizeLeft <= _poolReplaceBound) 
          { 
                //replace this pool 
                printf("replacing %d\n", i); 
                destroyPool(i); 
                if(_curPoolIdx == 0) constructPool(0); 
                else 
                { 
                 for(int j = i; j < _numPools-1; j++) 
                 { 
                   _pools[j] = _pools[j+1]; 
                 } 
                 _curPoolIdx--; 
                } 

          } 
          return; 
        } 
      } 
      #ifdef RT_SAFE_MEM 
        char str[50]; 
        sprintf(str, "Attempted to deallocate foreign memory at 0x%.8X.", ptr); 
        MessageBox(NULL, str, "Executor", MB_OK); 
      #endif 
     } 

}

如果有人看到一个错误或重大问题,让我知道。 谢谢!

+0

什么是疯狂的缩进? – 2012-08-01 18:52:45

+0

回答你的问题的一部分。如果你得到零字节的请求,你不应该返回NULL。将所有零字节的请求视为一个字节的请求,并且不会出错。 – jahhaj 2012-08-01 18:52:52

+0

免费前缀“_”是什么? – DanielKO 2012-08-01 19:47:36

我建议你做所有下面的步骤:

  1. 写测试程序来测试你的程序运行无缺陷或“有任何问题”
  2. 使用调试器发现错误,而不是SO的观众:-P
  3. 而不是发布你的代码的完整列表,你应该写出你的代码做什么 - 这将作为一个伟大的参考点在未来,也将是一个有用的文档什么(以及如何)你的代码