安装处理new operator无法获取足够内存时候的处理函数
在通常的情况下,调用new操作的时候,一般都不会去关心是否有足够的内存使得这个操作可以成功。但是做为一个完美的程序,有必要去处理一下内存不够的情况。
在默认情况下,内存分配失败会导致返回null或者抛出一个std::bad_alloc异常,所以需要在每次new的时候检查返回值是否为NULL或者在new上包裹一个try catch块。不过,除了每次不厌其烦得关心new是否成功,我们可以利用C++提供的set_new_handler函数来注册一个内存分配失败后的回调函数。set_new_handler函数接受一个如下定义的函数指针:
typedef void ( *new_handler )( );
当可用内存不足导致new操作失败的时候,如果有注册一个new_handler, new操作内部就会反复调用你注册的handler,然后重新尝试分配内存(所以你可以利用new_handler来释放一些不需要的内存,保证程序顺利运行)。当然,如果你没有注册new_handler,它就要抛出一个异常了。具体可以参考下面这段代码:
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
总结一下new_handler的用处
1 释放内存,保证new操作顺利执行
2 方便对new操作的异常处理,只需要注册一次,不需要每次在new操作之后检查或者捕捉异常
下面是new操作的用法举例:
1. 内存不足时,写log,然后释放不需要的内存
#include "stdafx.h"
#include <iostream>
#include <limits.h>
using namespace std;
void myHandler()
{
cerr<<"error doing new"<<endl;
//可以在这里释放一些内存
}
int _tmain(int argc, _TCHAR* argv[])
{
set_new_handler(myHandler);
int MemoryNeed = INT_MAX;
void *p = ::operator new(MemoryNeed);
return 0;
}
2. 也可以在首次调用new_handler之后更改/移除处理函数,实现灵活的内存分配逻辑:
#include "stdafx.h"
#include <iostream>
#include <limits.h>
using namespace std;
void myHandler2()
{
cerr<<"new way to handler insufficient memory"<<endl;
//在第二次执行后移除处理函数,利用默认机制抛出异常
set_new_handler(NULL);
}
void myHandler()
{
cerr<<"error doing new"<<endl;
//在第一次执行后设置新的处理函数
set_new_handler(myHandler2);
}
int _tmain(int argc, _TCHAR* argv[])
{
set_new_handler(myHandler);
int MemoryNeed = INT_MAX;
void *p = ::operator new(MemoryNeed);
return 0;
}
输出结果如下: