std::set_new_handler 如何提供更多内存

How does std::set_new_handler make more memory available?

本文关键字:内存 何提供 handler set new std      更新时间:2023-10-16

From std::set_new_handler

new-handler 函数是每当内存分配尝试失败时由分配函数调用的函数。它的预期目的是以下三件事之一:

  • 提供更多可用内存
  • 终止
  • 程序(例如,通过调用 std::终止)
  • 抛出类型为 std::bad_alloc
  • 或派生自 std::bad_alloc 的异常

以下重载会保证什么吗?

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();
    }
}
std::set_new_handler

使内存可用,它会设置分配失败时使用的新处理程序函数。

用户定义的 new-handler 函数可能能够提供更多可用内存,例如通过清除内存缓存或销毁一些不再需要的对象。 默认的 new-handler 这样做,它是一个空指针,因此分配内存失败只会引发异常,因为标准库无法知道程序中可能不再需要哪些对象。 如果您编写自己的新处理程序,则可能能够根据您对程序及其要求的了解将一些内存返回给系统。

下面是一个工作示例,说明了自定义新处理程序的功能。

#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()(正如我最近了解到的那样)。

相关文章: