当operator new申请一个内存失败的时候,它会进行如下的处理步骤:
1、如果存在客户指定的处理函数,则调用处理函数(new_handler),如果不存在则抛出一个异常。
2、继续申请内存分配请求。
3、判断申请内存是否成功,如果成功则返回内存指针,如果失败转向处理步骤1
为了自定义这个“用以处理内存不足”的函数new_handler,用户可以调用set_new_handler进行设置
这两个函数声明如下:
namespace std{
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
}
其中,new_handler是个typedef,定义一个函数指针,该函数没有参数,也没有返回值;
set_new_handler用于设置处理函数,设置p为当前处理函数,并返回之前的new_handler
当operator new无法满足内存分配需求时,它会不断调用new_handler函数,直到找到足够的内存。
因此,应该妥善设计new_handler函数,一个设计良好的new_handler必须做以下事情:
1、删除其它无用的内存,使系统具有可以更多的内存可以使用,为下一步的内存申请作准备。
实现此策略的办法是:程序一开始执行就分配一大块内存,当new_handler被调用时,将它们释放还给程序使用。
2、设置另外一个new_handler。
如果当前的new_handler不能够做到更多的内存申请操作,或者它知道另外一个new_handler可以做到,
则可以调用set_new_handler函数设置另外一个new_handler,这样在operator new下一次调用的时候,
可以使用这个新的new_handler。
3、卸载new_handler,使operator new在下一次调用的时候,因为new_handler为空抛出内存申请异常。
4、new_handler抛出自定义的异常
5、不再返回,调用abort或者exit退出程序
c++并不支持专属某一类的new_handler,但是如果需要,可以重载operator new,自己实现这个行为。
只需为class提供自己的set_new_handler和operator new即可。
在operator new中做如下事情:
1、首先调用标准的set_new_handler,自定义专属类的处理函数
2、调用global operator new,执行实际的内存分配。如果内存分配失败,刚才被安装的new_handler将被调用。
3、无论new成功还是失败,都必须在类自定义的operator new结束前恢复全局new_handler
这一部分的详细示例参考《effective c++》 条款49