1. 在使用operator new申请内存失败后,编译器并不是不做任何的努力直接抛出std::bad_alloc异常,在这之前,它会调用一个错误处理函数(new_handler)。
2. new_handler函数的处理方式策略:
(1)operator new会进行多次的内存分配尝试,这可能会使其下一次的内存分配尝试成功。在程序启动时分配一大块内存,然后在new_handler第一次被调用时释放它供程序使用。
(2)如果当前的new_handler不能获得更多的内存供operator new分配使用,但另一个new_handler却可以做到,则调用set_new_handler在自己的位置上安装另一个new_handler,当operator new下一次调用new_handler时,它会调用最新安装的那一个。
(3)将空指针传给set_new_handler,卸载new_handler。此时,当内存分配失败时,operator new则会抛出一个异常。
(4)抛出一个类型为bad_alloc或继承自bad_alloc的其他类型的异常。
(5)直接调用abort或exit结束应用程序。
3. set_new_handler的返回值是一个指向函数的指针,指向的是set_new_handler调用之前的异常处理函数。
5. 根据被分配对象的不同,采用不同的方法对内存分配失败进行处理:
2. new_handler函数的处理方式策略:
(1)operator new会进行多次的内存分配尝试,这可能会使其下一次的内存分配尝试成功。在程序启动时分配一大块内存,然后在new_handler第一次被调用时释放它供程序使用。
(2)如果当前的new_handler不能获得更多的内存供operator new分配使用,但另一个new_handler却可以做到,则调用set_new_handler在自己的位置上安装另一个new_handler,当operator new下一次调用new_handler时,它会调用最新安装的那一个。
(3)将空指针传给set_new_handler,卸载new_handler。此时,当内存分配失败时,operator new则会抛出一个异常。
(4)抛出一个类型为bad_alloc或继承自bad_alloc的其他类型的异常。
(5)直接调用abort或exit结束应用程序。
3. set_new_handler的返回值是一个指向函数的指针,指向的是set_new_handler调用之前的异常处理函数。
4. new_handler必须有主动退出功能,否则就会导致operator new内部死循环,new_handler的一般形式:
void MemErrorHandling()
{
if() // 如果有可能使得operator new成功
{
// process
return;
}
// 一下任一种方式主动退出:
// abort/exit 直接退出程序
// 或set_new_handler(其他new_handler)
// 或set_new_handler(NULL)
// 或throw bad_alloc()或其派生类
}
5. 根据被分配对象的不同,采用不同的方法对内存分配失败进行处理:
// 需要为每一个class提供专属的:
// set_new_handler
// operator new
// new_handler类型的静态成员
// 将其设置为类的new-handler处理函数
class A
{
public:
static std::new_handler set_new_handler(std::new_handler p) throw();
static void * operator new(std::size_t size) throw(std::bad_alloc);
static void MemoryErrorHandling();
private:
std::new_handler m_curHandler;
};
std::new_handler A::m_curHandler = NULL;
std::new_handler A::set_new_handler(std::new_handler p) throw()
{
std::new_handler oldHandler = m_curHandler;
m_curHandler = p;
return oldHandler;
}
void A::MemoryErrorHandling()
{
// process
}
void * A::operator new(std::size_t size) throw(std::bad_alloc)
{
set_new_handler(MemoryErrorHandling);
return ::operator new(size);
}