了解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.