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
}
}
如果有人看到一个错误或重大问题,让我知道。 谢谢!
答
我建议你做所有下面的步骤:
- 写测试程序来测试你的程序运行无缺陷或“有任何问题”
- 使用调试器发现错误,而不是SO的观众:-P
- 而不是发布你的代码的完整列表,你应该写出你的代码做什么 - 这将作为一个伟大的参考点在未来,也将是一个有用的文档什么(以及如何)你的代码
什么是疯狂的缩进? – 2012-08-01 18:52:45
回答你的问题的一部分。如果你得到零字节的请求,你不应该返回NULL。将所有零字节的请求视为一个字节的请求,并且不会出错。 – jahhaj 2012-08-01 18:52:52
免费前缀“_”是什么? – DanielKO 2012-08-01 19:47:36