当前位置: 首页 > 知识库问答 >
问题:

std::set_new_handler 如何使更多内存可用?

严高峻
2023-03-14

来自标准::set_new_handler

每当内存分配尝试失败时,分配函数都会调用new-handler函数。它的预期目的有三个:

  • 使更多内存可用
  • 终止程序(例如,通过调用 std::terminate)
  • 抛出类型 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();
    }
}

共有2个答案

汪建德
2023-03-14

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

#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(正如我最近学到的)。

谢善
2023-03-14

std::set_new_handler不生成可用存储器,它设置一个新处理函数,以便在分配失败时使用。

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

 类似资料:
  • 在开始之前,我需要说明我的应用程序使用了大量的字符串,这些字符串平均来说非常小,并且一旦创建就不会改变。 在Visual Studio 2010中,我注意到std::string的容量至少为30。即使编写,str的容量也是30。函数对此没有任何作用,尽管存在一个与std::vector同名的函数,并按预期工作,即减小容量,使容量==size。 null

  • 本文向大家介绍C++ 内存分配处理函数set_new_handler的使用,包括了C++ 内存分配处理函数set_new_handler的使用的使用技巧和注意事项,需要的朋友参考一下 一、函数的定义 函数在namespace std中有如下定义(C++98与C++11版本不一致): 二、函数介绍 该函数的作用是:当new操作或new[]操作失败时调用参数所指的new_p函数 异常安全: C++98

  • 我正在使用Nodejs。我计划增加Nodejs应用程序的内存限制。 在谷歌上搜索时,我发现了这篇文章:增加节点。js内存限制。 作者说他的服务器只有8GB的物理内存,但他的Nodejs进程使用的是28GB的内存。我假设它正在使用物理交换内存。文章还提到,一个著名的Nodejs框架的开发人员为他的Nodejs使用了15GB的内存限制。 我试图从其他编程语言中搜索一些示例。在Java中,将交换内存用于

  • 问题内容: 使用以下Java选项启动Apache Tomcat(Atlassian Confluence)实例: 但是,我看到启动后,它很快就耗尽了虚拟服务器上可用的1GB内存中的大部分。 总消耗的内存(堆+ PermGen)是否不应该保持在使用- Xmx指定的值以下?这引起的问题之一是我无法使用关闭脚本关闭服务器,因为它试图生成具有256MB内存的JVM,该JVM因不可用而失败。 问题答案: T

  • 正如标题所说,我正在尝试为我的容器分配更多的内存。我正在使用docker中心的一个名为“aallam/tomcat-mysql”的图像,以防相关。 当我在没有任何特殊标志的情况下正常启动时,内存限制为2GB(即使我读到内存是无界的,如果没有设置) 这是我的码头工人数据 我试着像这样显式地设置内存,但结果相同 我已经读到,可能是虚拟机限制了它。但为什么docker统计数据显示容器大小限制为2GB?