operator new之错误处理函数new_handler

29 篇文章 1 订阅

就像可以用atexit来注册main的退出处理函数一样,我们也可以用std::set_new_handler来注册operator new的错误处理函数。

operator new无法满足某一内存分配需求时,operator new会抛出异常。

但是当operator new无法满足某一内存分配需求而抛出异常之前,会先调用一个用户指定的错误处理函数,即所谓的new-handler

operator new无法满足内存分配需求--->(循环)调用执行用户指定的错误处理函数new-handler--->operator new抛出异常

 

用户可以调用std::set_new_handler接口指定这个“用以处理内存不足”的函数new-handler

new-handler是声明于<new>的一个标准程序库函数,如下所示:

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

可知:

1)new_handler是通过typedef定义出的一个指针指向函数,该函数不返回任何东西

2)set_new_handler:则是获得一个new_handler并返回一个new_handler的函数

set_new_handler函数的实现大概如下所示:

new_handler set_new_handler(new_handler p) throw
{
new_handler oldHandler = m_curHandler;
m_curHandler = p;
return oldHandler;
}

3)声明式的尾端throw()是一份异常明细,表示该函数不抛出任何异常

注:当operator new无法满足内存申请时,operator new会不断反复调用new-handler函数,直到找到足够内存。

示例如下:

#include <stdlib.h>	//for abort()
#include <iostream>
void outOfMem()
{
	std::cerr<<"operator new unable to satisfy request for memory, try allocate memory again.\n";
}
int main()
{
	std::set_new_handler(outOfMem );
	int *buf = new int[1000000000L];
      Delete []buf;
	return 0;
}
测试结果如下所示:

通过以上测试可知,当operator new无法满足内存分配时,如果你通过std::set_new_handler设置了operator new的错误处理函数new_handler后,就会重复调用new_handler函数直到找到足够的内存(如果你在new_handler内调用了abort或者exitnew_handler会只被调用一次)。

 

跟进一步得出结论,设计一个良好的new_handler函数是很重要的。

new_handler能选择以下几个处理方式中的一个方式进行处理是比较合理的,也是应该的。

处理方式1:让更多内存被使用

程序刚开始时就申请分配一大块内存,当new_handler被调用时就释放它还给程序使用。

处理方式2:安装另一个new_handler

如果new_handler1无法处理时,就在new_handler1内部调用set_new_handler设置new_handler2来处理,下次就会调用new_handler2来处理。

 

处理方式3:卸载new_handler

std::set_new_handler(NULL)来卸载new_handler,则operator new在内存分配失败时不会调用错误处理函数new_handler而直接抛出异std::bad_alloc并且Abort掉程序。

 

处理方式4:抛出std::bad_alloc或者派生自std::bad_alloc的异常。

这样异常不会被operator new捕捉,因此会被传播到内存索求处。

处理方式5:调用abortexit

 

下面这五种处理方式中的几种方式,进行编码实现。

处理方式2:安装另一个new_handler

如果new_handler1无法处理时,就在new_handler1内部调用set_new_handler设置new_handler2来处理,下次就会调用new_handler2来处理。

#include <stdlib.h>	//for abort()
#include <iostream>
void handle_outOfMem2()
{
	std::cerr<<__FUNCTION__<<":operator new unable to satisfy request for memory, try allocate memory again.\n";
}
void handle_outOfMem()
{
	std::cerr<<__FUNCTION__<<":operator new unable to satisfy request for memory, try allocate memory again.\n";
	std::set_new_handler(handle_outOfMem2);
}
int main()
{
	std::set_new_handler(handle_outOfMem );
	int *buf = new int[1000000000L];
      delete []buf;
	return 0;
}

测试结果如下所示:

处理方式3:卸载new_handler

std::set_new_handler(NULL)来卸载new_handler,则operator new在内存分配失败时不会调用错误处理函数new_handler

#include <stdlib.h>	//for abort()
#include <iostream>
void handle_outOfMem()
{
	std::cerr<<__FUNCTION__<<":operator new unable to satisfy request for memory, try allocate memory again.\n";
	std::set_new_handler(NULL);
}
int main()
{
	std::set_new_handler(handle_outOfMem );
	int *buf = new int[1000000000L];
	delete []buf;
	return 0;
}

测试结果如下所示:

处理方式5:调用abortexit

#include <stdlib.h>	//for abort()
#include <iostream>
void handle_outOfMem()
{
	std::cerr<<"operator new allocate memory failed, try again.\n";
	abort();
}
int main()
{
	std::set_new_handler(handle_outOfMem );
	int* buf = new int[1000000000000000L];
	delete []buf;
	return 0;
}
测试结果如下所示:




在C++开发的工程项目中,一般可能需要对具体class注册自定义的new_handler,具体可以参考《Effective C++ 改善程序与设计的55个具体做法》。


(完)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值