Effective C++ — 条款49:了解new-handler的行为

来源:互联网 发布:广州网络维护 编辑:程序博客网 时间:2024/05/16 08:20

了解new-handler的行为






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

当operator new抛出异常以反映一个未获得满足的内存需求之前,它会先调用一个客户指定的错误处理函数,一个所谓的new_handler. 为了指定这个

"用以处理内存不足"的函数,客户必须调用set_new_handler,它是声明于<new>的一个标准程序库函数;

//set_new_handler函数  namespace std {      typedef void (*new_handler)();      new_handler set_new_handler(new_handler p) throw();  //异常声明,表示该函数不抛出任何异常  }  

如你所见,new_handler是一个typedef,定义出一个指针指向函数,该函数没有一个参数也不返回任何一个东西. set_new_hanler则是"获得一个

new_handler"并返回一个new_handler"的函数. set_new_handler生命式尾端的"throw()"是一份异常明细,表示该函数不抛出任何异常.

set_new_handler的尝试实现:

/*该函数接收一个返回值为空,参数为空的函数指针作为参数,最后返回一个返回值和参数均为空的函数指针*/    static void (* __set_new_handler(void (*__f)()))()       {        void (* __old)() = __new_alloc_oom_handler;       //保存原有处理例程        __new_alloc_oom_handler = __f;                    //重新指定异常处理例程        return(__old);    }    

set_new_handler的参数也是一个指针,指向operator new无法分配足够内存时该被调用的函数.其返回值也是一个指针,指向set_new_handler被调用

前正在执行(但马上就要被替换)的那个new_handler函数.具体如何使用set_new_handler. 它的思想在空间配置器当中起着举足轻重的位置. 所以我们

可以去看看这个博客: 然后再过来看set_new_handler可能会更好的理解它.  一级空间配置器博客  


在operator new的无法分配足够空间的时候,就会尝试调用new_handler中的用户自定义清除空间函数. 如果空间还不够那么operator new就会反

复调用new_handler,直到找到足够的内存.


当然如果你想设计出来一个优秀的new_handler函数必须做下面的事情:

***1.让更多的内存可被使用. 这便造成operator new内的下一次内存分配动作可能成功. 实现此策略的第一个做法就是,程序一开始执行就分配一大

块内存,而后当new_handler第一次被调用,将他们释还给程序使用.

***2.安装另一个new_handler. 如果目前这个new_handler无法取得更多可用的内存,或许他知道另外那个new_handler有此能力.果真如此,目前这个

new_handler就可以安装另外那个new_handler以替换自己(只要调用set_new_handler). 下次当operator new调用new_handler,调用的将是最新安装的

那个.(这个旋律的变奏之一是让new_handler修改自己的行为,于是当它下次被调用的时候,就会做某些不同的事情了. 为达到目的,做法之一是令

new_handler修改"会影响new_handler行为"的static数据,namespace数据或global数据).

***3.卸除new_handler 也就是将Null指针传给set_new_handler. 一旦没有安装任何new_handler,operator new会在内存分配不成功时抛出异常.

***4.抛出bad_alloc的异常 这样的异常不会被operator new捕捉,因此会被传播到内存索求处.

***5. 不返回,通常调用abort或exit.