CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  工具平台和程序库

内存池使得全局new失败?

楼主nbb()2003-12-02 22:58:10 在 C/C++ / 工具平台和程序库 提问

最近偶作了一个内存缓冲池,但它运行时使得全局   ::new   的   HeapAlloc   函数出故障:  
   
  //////////////头文件mem.h/////////////  
  #pragma   once  
  #include   <vector>  
  #include   <algorithm>  
  #include   <assert.h>  
  #include   <windows.h>  
   
  #define   MAX_OBJ_SZ   64  
   
  class   chunk;  
  class   FixedAllocator;  
  class   GenAllocator;  
  template   <class   T>   class   Allocator;  
   
  class   chunk   //块表  
  {  
  public:  
  void*   allocatebytes(DWORD   bksz);//分配bksz大小的块,该bksz必须是初始化时的默认大小,分配不到则返回0  
  void     deallocatebytes(void*   pbyte,DWORD   bksz);//释放bksz大小的块,同样必须是初始化时的默认大小  
  void     init(int   blocksize=4);//创建chunk时直到init才真正分配内存,并初始化  
  void     release();//完全释放内存  
   
  char   *   pData;//256个块的数组指针  
  char   *   Head;//链表可用头指针  
  DWORD       Available;//可用数量  
  };  
   
  class   FixedAllocator   //块表数组  
  {  
  public:  
  void   *   allocatefixedblock();//分配大小为block_size的块  
  void       deallocatefixedblock(void*   pfixed);//释放大小是block_size的块  
  explicit   FixedAllocator(int   blocksize);//初始化块表vector,大小存入block_size  
  ~FixedAllocator();  
  bool   isInpool(void*   p);//判断p是否在本vector内部  
  void   init();   //在构造后合适的时机初始化内部的第一chunk,以使得迭代器不指空  
  private:  
  int       block_size;  
   
  typedef   std::vector<chunk>   Chunks;  
  Chunks     chunkstable;  
  Chunks::iterator     pLastAlloc;  
  Chunks::iterator     pLastDealloc;  
  FixedAllocator();  
  friend   class   GenAllocator;  
  };  
  class   GenAllocator  
  {  
  public:  
  void*   allocate(int   size);//从内部的FixedAllocator中,找一个符合blocksize的分配块(如没有则创建该FixedAllocator)  
  void     deallocate(void*   pblock,int   size);//释放大小为blocksize的块  
  explicit   GenAllocator(int   bkszauto,int   maxblocksize=MAX_OBJ_SZ);//bkszauto:最可能大小,pool_初始化时默认构造第一个Fixed大小  
  ~GenAllocator();  
  bool     Inpool(void*   p);//判断p是否在整个缓冲池内,是则真,不是则假  
   
  private:  
  int   maxsize;  
  int   autosz;  
  typedef   std::vector<FixedAllocator>   MemBk;  
  MemBk   pool_;  
  MemBk::iterator   pLastAllo_;  
  MemBk::iterator   pLastDeallo_;  
  GenAllocator();  
  GenAllocator(const   GenAllocator&);  
  GenAllocator&   operator=(const   GenAllocator&   rhs);  
  };  
   
  template   <class   T=int>         //T:   类型名称,用于控制特化  
  class   Allocator                       //用int型表示未特化的模板  
  {  
  static   GenAllocator   *pAllo;//所有的公用  
  public:  
  Allocator(){   pAllo=new   GenAllocator(4);}  
   
  explicit   Allocator(int   auto_size,int   maxsz=MAX_OBJ_SZ){  
  pAllo=new   GenAllocator(auto_size,maxsz);  
  };//创建出唯一的GenAllocator,其下属的FixdeGenAllocator规格是auto_size,GenAllocator中至少有一个chunk(不制定规格的话其大小是默认:4bytes)  
  ~Allocator(){   delete   pAllo; }  
   
  void*   allocate(int   size)const{  
  return   pAllo->allocate(size);  
  };  
  void     deallocate(void*   pblock,int   size)const{  
  pAllo->deallocate(pblock,size);  
  };  
  };  
  问题点数:100、回复次数:13Top

1 楼nbb()回复于 2003-12-02 22:58:57 得分 0

////////////////实现文件mem.cpp//////////////////  
  #   include   "stdafx.h"  
  #include   "memory.h"  
  #pragma   once  
   
  GenAllocator*   Allocator<int>::pAllo=0;  
   
  void   chunk::init(int   blocksize)//默认的规格是4BYTE  
  {  
  assert(blocksize%4==0&&blocksize!=0);  
  rty:  
  pData=::new   char[256*blocksize];  
  Available=256;  
  Head=pData;  
  register   int*   p;  
  register   int   pnext=(int)pData;//指向块n的头4BYTE  
  for(int   n=0;n<256;++n){  
  p=(int*)pnext;//p指向每块开始  
  pnext+=blocksize;//前跳  
  *p=pnext;//填入n+1块的地址到第n块,使得前一块指向下一块  
  }  
  *p=0;//最后一块必须为0  
  }  
  void   chunk::release(){   delete[]   pData;}  
   
  void*   chunk::allocatebytes(DWORD   bksz)  
  {  
  assert(Available>0&&Available<=256);  
  assert((Head-pData)%bksz==0);  
  --Available;  
  char   *   ptep=Head;  
  Head=reinterpret_cast<char*>(*(int*)(Head));//用Head块的下一块填充Head  
  assert((Head-pData)%bksz==0);  
  return   ptep;  
  }  
  void     chunk::deallocatebytes(void*   pbyte,DWORD   bksz)  
  {  
  assert(pbyte!=0&&(((char*)pbyte-pData)%bksz==0)   );  
  assert(   ((char*)pbyte-pData)/bksz<=256);  
  assert(Available<256);  
  ++Available;  
  char*   ptep=Head;//备份  
  Head=(char*)pbyte;//调整Head指向释放的块头  
  *(int*)Head=int(ptep);//调整Head的链指针使指向原Head  
  }  
   
  ///////////////////////////////////////////////////////  
  FixedAllocator::FixedAllocator(int   blocksize):   block_size(blocksize){  
  chunkstable.push_back(   chunk()   );//至少有一个chunk  
  pLastAlloc=chunkstable.begin();  
  pLastDealloc=pLastAlloc;  
  pLastAlloc->Available=256;  
  pLastAlloc->pData=0;  
  pLastAlloc->Head=0;  
  }  
  FixedAllocator::~FixedAllocator(){  
  for(Chunks::iterator   it3=chunkstable.begin();it3!=chunkstable.end();++it3){  
  if(it3->Available!=256){  
  char*   p1="警告"; char*   p2="空间尚在使用,已被强行释放";  
  ::MessageBox(0,p2,p1,MB_OK);  
  }  
  it3->release();  
  }  
  }  
  void   FixedAllocator::init(){  
  chunkstable.clear();  
  pLastAlloc->init(block_size);//chunk分配内存并初始化  
  }  
   
  void*   FixedAllocator::allocatefixedblock()  
  {  
  assert(pLastAlloc<chunkstable.end());  
  if(pLastAlloc->Available!=0){//前次使用的块有空,直接分配  
  return   pLastAlloc->allocatebytes(block_size);  
  }  
  if((pLastAlloc+1<chunkstable.end())&&(pLastAlloc+1)->Available!=0){//前次使用的块已无空,但下一个有  
  ++pLastAlloc;  
  return   pLastAlloc->allocatebytes(block_size);  
  }  
  if((pLastAlloc-1>=chunkstable.begin())&&(pLastAlloc+1)->Available!=0){//上一个有  
  --pLastAlloc;  
  return   pLastAlloc->allocatebytes(block_size);  
  }  
  for(Chunks::iterator   it1=chunkstable.begin();it1!=chunkstable.end();++it1){//搜索有空的chunk分配  
  if(it1->Available!=0){   pLastAlloc=it1;  
  return   it1->allocatebytes(block_size);   }  
  }  
  chunkstable.push_back(   chunk()   );//都没空,加新的chunk  
  pLastAlloc=chunkstable.end()-1;  
  pLastAlloc->init(block_size);//chunk分配空间(因为无构造函数)  
  return   pLastAlloc->allocatebytes(block_size);  
  }  
  void   FixedAllocator::deallocatefixedblock(void*   pfixed)  
  {  
  assert(pLastDealloc<chunkstable.end());  
  __int64   tp=   (char*)pfixed   -   (pLastDealloc->pData);//试探是否在最后一次返还块(tp是与它的距离)  
  if(   tp>0   &&   tp<256*block_size   ){//是则直接释放  
  pLastDealloc->deallocatebytes(pfixed,block_size);  
  return;  
  }  
  for(Chunks::iterator   it2=chunkstable.begin();it2!=chunkstable.end();++it2){//否则搜寻在哪一块  
  __int64   tp=   (char*)pfixed   -   it2->pData;  
  if(tp>0   &&   tp<256*block_size   ){  
  it2->deallocatebytes(pfixed,block_size);  
  pLastDealloc=it2;  
  return;  
  }  
  }  
  char*   p1="严重错误"; char*   p2="返回的空间不能回收";  
  int   rv=::MessageBox(0,p2,p1,MB_OK);  
  exit(rv);  
  }  
   
  bool   FixedAllocator::isInpool(void*   p){  
  for(Chunks::iterator   it=chunkstable.begin();it!=chunkstable.end();++it){  
  if(it->pData<=(char*)p   &&   (it->pData+256*block_size)>(char*)p   )   return   1;  
  }  
  return   0;  
  }  
   
  ////////////////////////////////////////////////////  
  GenAllocator::GenAllocator(int   bkszauto,int   maxblocksize)  
  :   maxsize(maxblocksize),autosz(bkszauto){  
  pool_.push_back(   FixedAllocator(bkszauto)   );//至少构造一个,使得迭代器有值  
  pLastAllo_=pLastDeallo_=pool_.begin();  
  pLastAllo_->init();//初始化推入vector中的第一个FixedAllocator  
  }  
  GenAllocator::~GenAllocator()  
  {  
  }  
   
  void*   GenAllocator::allocate(int   size)  
  {  
  if(size>maxsize)   return   ::operator   new(size);  
  size+=3;//4-1  
  size&=0xfc;//4对齐  
  if(pLastAllo_->block_size==size){//猜测命中直接分配  
  return   pLastAllo_->allocatefixedblock();  
  }  
  for(MemBk::iterator   it4=pool_.begin();it4!=pool_.end();++it4){//搜寻,如果已有该大小的分配,接着调整pLastAllo_  
  if(it4->block_size==size){  
  pLastAllo_=it4;  
  return   it4->allocatefixedblock();  
  }  
  }  
  pool_.push_back(FixedAllocator(size));//没有找到需要大小的,直接构造  
  pLastAllo_=pool_.end()-1;  
  pLastAllo_->block_size=size;  
  return   pLastAllo_->allocatefixedblock();  
  }  
  void   GenAllocator::deallocate(void*   pblock,int   size)  
  {  
  if(size>maxsize)   return   ::operator   delete(pblock);  
  size+=3;//4-1  
  size&=0xfc;//4对齐  
  if(pLastDeallo_->block_size==size){//猜测命中  
  pLastAllo_->deallocatefixedblock(pblock);  
  return;  
  }  
  for(MemBk::iterator   it4=pool_.begin();it4!=pool_.end();++it4){  
  if(it4->block_size==size){  
  it4->deallocatefixedblock(pblock);  
  pLastDeallo_=it4;  
  return;  
  }  
  }  
  char*   p1="严重错误"; char*   p2="返回的空间不能回收";  
  int   rv=::MessageBox(0,p2,p1,MB_OK);  
  exit(rv);  
  }  
  bool   GenAllocator::Inpool(void*   p){  
  for(MemBk::iterator   it=pool_.begin();it!=pool_.end();++it){  
  if(it->isInpool(p))   return   1;  
  }  
  return   0;  
  }Top

2 楼nbb()回复于 2003-12-02 22:59:24 得分 0

////////////////程序文件tst.cpp////////////////////  
   
  #include   "stdafx.h"  
  #include   "memory.h"  
  using   namespace   std;  
   
  class   one{  
  int   ss[32];  
  };  
  int   _tmain(int   argc,   _TCHAR*   argv[])  
  {  
  Allocator<int>   alloc1;  
   
  one*   pone=new   one;   //这里出故障,可追踪到是API的   HeapAlloc   函数,它是   new   的地层函数  
   
  cout<<pone<<endl;     //也可能这里失败,同样可追踪到   HeapAlloc   函数出故障,奇怪的是cout能够输出结果  
  //感觉好像是跟运行库有关?   请高手指点  
  return   0;  
  }  
  Top

3 楼nbb()回复于 2003-12-02 23:06:11 得分 0

编译器是VC71.NETTop

4 楼smalltalk(老徐)回复于 2003-12-02 23:15:52 得分 10

niu   biTop

5 楼jyc_nj(老蔣)回复于 2003-12-03 14:02:41 得分 0

不好意思,   请问one*   pone=new   one;怎样调用到你的函数?Top

6 楼yjh1982(血精灵)回复于 2003-12-03 14:34:51 得分 20

应该是某个在main函数之前的操作引起(如static   变量)Top

7 楼nbb()回复于 2003-12-03 22:30:43 得分 0

“不好意思,   请问one*   pone=new   one;怎样调用到你的函数?”  
   
  那是使用   ::newTop

8 楼jyc_nj(老蔣)回复于 2003-12-04 09:39:12 得分 0

全局的::operator   new么?  
  你在哪里重载了new   ?   程序太长;)Top

9 楼nbb()回复于 2003-12-04 13:25:27 得分 0

上面的没给出来:(不过已经可以使得全局的   ::NEW   出异常)  
   
  const   static   AllocGen;  
   
  class   SmallObj   //需要时直接对其继承  
  {  
  SmallObj(const   SmallObj&   rhs);  
  public:  
  SmallObj(){}  
  virtual   ~SmallObj(){}  
  //explicit   SmallObj(int   auto_size,int   maxbksz=MAX_OBJ_SZ);//创建出唯一的GenAllocator,其下属的FixdeGenAllocator规格是bk_size,GenAllocator中至少有一个chunk(不制定规格的话其大小是默认:4bytes)  
  static   void*   operator   new(size_t   size){  
  return   AllocGen.allocate(size);  
  }  
  static   void     operator   delete(void*   p,size_t   size){  
  AllocGen.deallocate(p,size);  
  }  
  };  
  Top

10 楼jyc_nj(老蔣)回复于 2003-12-04 14:07:23 得分 40

觉得全局的operator   new,你既不能重载,还要保证它的调用不会出错(不会被你重复调用)  
  我觉得显式的分配内存,容易控制.Top

11 楼smaxll(古颜)回复于 2003-12-05 09:42:54 得分 20

关注Top

12 楼holy198048(holy)回复于 2003-12-05 10:27:01 得分 10

关注Top

13 楼nbb()回复于 2003-12-06 18:13:38 得分 0

已经解决,是标准库多处地方需要的默认构造函数和析构函数与上面的某些类有冲突,重新设计了相关的函数后解决Top

相关问题

  • 全局线程函数中创建 csocket 失败???why?
  • 全局变量如何在使用后从内存中清除.
  • 请教全局二维数组变量的内存分配!
  • 请教关于DLL使用全局内存块的问题
  • 大家都怎样处理申请内存失败的问题?
  • 调用ReadProcessMemory访问其他进程的内存失败
  • 请问: LOCALALLOC和GLOBALLOC有什么区别? 全局内存和局部内存有什么区别?
  • 如何定义一个动态分配内存的全局变量?
  • 二叉树全局结构变量分配内存的释放问题
  • 请问,全局变量在内存中是如何存放的?急急!

关键词

  • 内存
  • genallocator
  • plastalloc
  • fixedallocator
  • bksz
  • chunkstable
  • pallo
  • chunk
  • 初始化
  • allocatebytes

得分解答快速导航

  • 帖主:nbb
  • smalltalk
  • yjh1982
  • jyc_nj
  • smaxll
  • holy198048

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo