C++ 了解new-handler的行为

20180408 C++ 了解new-handler的行为


当operator new 无法满足某一个内存分配需求时,他会抛出异常,以前他会返回一个null指针,某些旧式编译器目前也还这么做。




当operator new 抛出异常以反映一个未获满足的内存需求之前,他会先调用一个客户指定的错误处理函数,一个所谓的new-handler,为了指定这个函数,客户必须调用set_new_handler,这个函数是声明于<new>的一个标准程序库函数:


namespace std
{
  typedef void (*new_handler)();
  new_handler set_new_handler(new_handler p) throw();
}




上述代码中,new_handler是个typedef,定义了一个指针指向函数,该函数没有参数也不返回任何东西,set_new_handler则是“获得一个new_handler并返回一个new_handler”的函数,set_new_handler声明式尾端的“throw()”是一份异常明细,表示该函数不抛出任何异常(虽然事实更有趣些)。


set_new_handler的参数是一个指针,指向 operator new无法分配足够内存时该被调用的函数。其返回值也是个指针,指向  set_new_handler被调用前正在执行(但马上要被替换)的那个 new_handler函数。
可以这样使用new-handler:


//以下是当operator new无法分配足够内存时,该被调用的函数
void outOfMem()
{
  std::cerr<<"Unable to satisfy request for memory\n";
  std::abort();
}


int main()
{
  std::set_new_handler(outOfMem);
  int* pBigDataArray = new int[100000000L];
  ...
}


就本例而言,若operator new无法为100000000个整数分配足够空间,会被调用,于是程序在发出一个信息之后夭折。




当operator new 无法满足内存申请时,他会不断调用new-handler函数,直到找到足够内存,引起反复调用的代码这里不再赘述,设计良好的new-handler函数必须做以下事情:
(1)让更多内存可被调用:这就是造成oprator new 里的下一次内存分配动作可能造成成功。
(2)安装另一个new-handler:若目前这个new-handler无法取得更多可用内存,或许他知道另外哪个new-hanlder有此能力。
(3)卸除new-handler:也就是将null指针传给set_new_handler。
(4)抛出bad_alloc(或派生自bad_alloc)的异常:这样的异常不会被operator new捕捉,因此会被传播到内存索求处。
(5)不返回,通常调用abort或exit。


这些选择让你在实现new-handler函数时拥有很大弹性。






现在,假设你打算处理Widget类的内存分配失败情况,即:
class Widget
{
public:
  static std::new_handler set_new_handler(std::new_handler p) throw();
  static void* operator new(std::size_t size) throw(std::bad_alloc);
private:
  static std::new_handler currentHandler;
};


Static成员必须在类的定义式之外定义,即:
std::new_handler Widget::currentHandler = 0;
                         //在类实现文件里初始化为null




/*******************剩下的都没看懂**********************/


























































































阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页