new-handler函数是分配函数在内存分配尝试失败时调用的函数。其预期目的是三件事之一:
以下超载会保证什么吗?
void * operator new(std::size_t size) throw(std::bad_alloc){
while(true) {
void* pMem = malloc(size);
if(pMem)
return pMem;
std::new_handler Handler = std::set_new_handler(0);
std::set_new_handler(Handler);
if(Handler)
(*Handler)();
else
throw bad_alloc();
}
}
答案 0 :(得分:12)
std::set_new_handler
不提供内存,它设置了一个新的处理程序函数,以便在分配失败时使用。
用户定义的新处理程序函数可能能够提供更多可用内存,例如通过清除内存缓存,或销毁一些不再需要的对象。默认的新处理程序不执行此操作,它是一个空指针,因此无法分配内存只会引发异常,因为标准库无法知道程序中可能不再需要哪些对象。如果您编写自己的新处理程序,则可能会根据您对程序及其要求的了解将一些内存返回给系统。
答案 1 :(得分:6)
以下是一个工作示例,说明自定义新处理程序的功能。
#include <iostream>
#include <new>
/// buffer to be allocated after custom new handler has been installed
char* g_pSafetyBuffer = NULL;
/// exceptional one time release of a global reserve
void my_new_handler()
{
if (g_pSafetyBuffer) {
delete [] g_pSafetyBuffer;
g_pSafetyBuffer = NULL;
std::cout << "[Free some pre-allocated memory]";
return;
}
std::cout << "[No memory to free, throw bad_alloc]";
throw std::bad_alloc();
}
/// illustrates how a custom new handler may work
int main()
{
enum { MEM_CHUNK_SIZE = 1000*1000 }; // adjust according to your system
std::set_new_handler(my_new_handler);
g_pSafetyBuffer = new char[801*MEM_CHUNK_SIZE];
try {
while (true) {
std::cout << "Trying another new... ";
new char[200*MEM_CHUNK_SIZE];
std::cout << " ...succeeded.\n";
}
} catch (const std::bad_alloc& e) {
std::cout << " ...failed.\n";
}
return 0;
}
我没有建议生产代码的演示策略,可能太沉重,无法预测,在调用new_handler一次后,有多少分配会成功。我在我的系统上观察到一些成功的分配(使用数字来查看你的系统会发生什么)。这是一个可能的输出:
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... [Free some pre-allocated memory] ...succeeded.
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... ...succeeded.
Trying another new... [No memory to free, throw bad_alloc] ...failed.
Process returned 0 (0x0) execution time : 0.046 s
Press any key to continue.
相反,从我的角度来看,释放安全缓冲区只是为了以安全的方式终止你的程序。即使正确的异常处理需要内存,如果没有足够的可用内容,也会调用abort()
(as I learned recently)。