之前,曾对new做了一些总结,详见"
new的理解".
在看《effective C++》第8章时,对内存分配有一些新的认识,这里主要讲一讲对set_new_handler的理解。
当使用nothrow_t版的operator new时,如果不能满足一个内存分配请求,会返回一个NULL指针。
void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw()
当使用throw (std::bad_alloc)版的operator new时,如果不能满足一个内存分配请求,会抛出一个异常。
void* operator new (std::size_t size) throw (std::bad_alloc)
在 operator new 因一个无法满足的内存请求而抛出一个异常之前,它先调用一个可以由客户指定的被称为 new-handler 的错误处理函数。
为了指定这个错误处理函数,客户需先设置 set_new_handler函数,内存分配失败后会反复调用这个new-handler 的错误处理函数。
错误处理函数的原型:
typedef void (*new_handler)(); //一个函数指针
set_new_handler的原型:
new_handler currentHandler = 0;
new_handler set_new_handler(new_handler p) //设置当前new_handler,返回前一个new_handler
{
new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
我在下例中,做了2个new-handler:
void newHandlerFree(); //释放一些内存,确保下次能够分配内存
输出结果:
在看《effective C++》第8章时,对内存分配有一些新的认识,这里主要讲一讲对set_new_handler的理解。
当使用nothrow_t版的operator new时,如果不能满足一个内存分配请求,会返回一个NULL指针。
void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw()
当使用throw (std::bad_alloc)版的operator new时,如果不能满足一个内存分配请求,会抛出一个异常。
void* operator new (std::size_t size) throw (std::bad_alloc)
在 operator new 因一个无法满足的内存请求而抛出一个异常之前,它先调用一个可以由客户指定的被称为 new-handler 的错误处理函数。
为了指定这个错误处理函数,客户需先设置 set_new_handler函数,内存分配失败后会反复调用这个new-handler 的错误处理函数。
错误处理函数的原型:
typedef void (*new_handler)(); //一个函数指针
set_new_handler的原型:
new_handler currentHandler = 0;
new_handler set_new_handler(new_handler p) //设置当前new_handler,返回前一个new_handler
{
new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
我在下例中,做了2个new-handler:
void newHandlerFree(); //释放一些内存,确保下次能够分配内存
void outOfMemHandler(); //没有内存了,set_new_handler(0),不再反复调用new-handler
#include <iostream>
using namespace std;
//buffer size
const int SIZE=99999999;
char *buffer = NULL;
//placement new
//void* operator new (std::size_t size, void* ptr) throw();
//重载nothrow new: int* p = new(std::nothrow) int[100000000ul]
//struct nothrow_t {}; 一个空结构体,为了区分throw new.
//void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw()
//重载throw new
void* operator new (std::size_t size) throw (std::bad_alloc)
{
if (size == 0)
//如果内存请求大小为0,设为1
size = 1;
void *p_alloc = 0;
// while (!(p_alloc = ::new char[size])) 不能用std ::new, 依旧会调用到这里的operator new
while (!(p_alloc = malloc(size)))
{
cout << "Memory allocation failed"<<endl;
new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);
if (globalHandler)
(*globalHandler)();
else //不再处理 new-handler
throw std::bad_alloc();
}
return p_alloc;
}
//没有内存了,set_new_handler(0),不再反复调用new-handler
void outOfMemHandler()
{
cout<<"Out of memory"<<endl;
set_new_handler(0);
}
//释放一些内存,确保下次能够分配内存
void newHandlerFree()
{
if(NULL != buffer)
{
cout << "Free some memory(buffer)"<<endl;
delete buffer;
buffer = NULL;
return;
}
cout << "No more memory for free"<<endl;
set_new_handler(outOfMemHandler);
}
int main()
{
//buffer将会在后续内存分配失败后释放
//这里buffer的size随着不同的环境调整,主要是为了制造没有足够内存分配
buffer = new char[SIZE*4999];
set_new_handler(newHandlerFree);
try
{
while (true)
{
new char[SIZE*4999];
cout << "Memory allocation successful"<<endl;
}
}
catch (const std::bad_alloc& e)
{
cout <<"Catch exception: "<< e.what() << endl;
}
}
输出结果:
... ...
Memory allocation successful
Memory allocation successful
Memory allocation successful
Memory allocation successful
Memory allocation successful
Memory allocation successful
Memory allocation failed
Free some memory(buffer)
Memory allocation successful
Memory allocation failed
No more memory for free
Memory allocation failed
Out of memory
Memory allocation failed
Catch exception: St9bad_alloc