c++中new_handler

详细可参考 《effective c++》第三版 条款49:了解new_handler的行为
当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

#include <iostream>
#include <new>

using namespace std;
void handler1()
{
	std::cout << "Memory allocation failed, terminating1\n";
	//std::set_new_handler(nullptr);
	abort();

}

void handler()
{
	//extern void *handler1;
	std::cout << "Memory allocation failed, terminating\n";
	std::set_new_handler(handler1);

}


int main()
{
	set_new_handler(handler);
	try {
		while (true) {
			new int[100000000ul];
		}
	}
	catch (const std::bad_alloc& e) {
		std::cout << e.what() << '\n';
	}


	cout << "hello" << endl;
}

先调用handler,后调用hanlder1,最后抛出异常。





猜你喜欢

转载自blog.csdn.net/alatebloomer/article/details/80536655