了解新处理程序的行为 我正在阅读Scott Meyers的C++ 55,并从第49条中得到一个问题:

了解新处理程序的行为 我正在阅读Scott Meyers的C++ 55,并从第49条中得到一个问题:,c++,new-operator,dynamic-memory-allocation,C++,New Operator,Dynamic Memory Allocation,当操作员new无法满足内存请求时,它调用 新的处理函数会重复执行,直到找到足够的内存为止 设计良好的newhandler函数必须执行以下操作之一: 使更多的内存可用 安装不同的新处理程序 卸载新的处理程序 抛出异常 不归 当new无法分配内存时,意味着内存不足,问题是newhandler如何以及从何处分配更多内存 您能解释一下所有这些步骤吗?这取决于具体实施。我可以告诉你我通常的做法: 1) 新处理程序在启动时分配大量内存作为备用 2) 当普通分配失败时,新的处理程序将投入其储备 3) 控制

操作员new
无法满足内存请求时,它调用 新的处理函数会重复执行,直到找到足够的内存为止

设计良好的newhandler函数必须执行以下操作之一:

  • 使更多的内存可用
  • 安装不同的新处理程序
  • 卸载新的处理程序
  • 抛出异常
  • 不归
new
无法分配内存时,意味着内存不足,问题是newhandler如何以及从何处分配更多内存


您能解释一下所有这些步骤吗?

这取决于具体实施。我可以告诉你我通常的做法:

1) 新处理程序在启动时分配大量内存作为备用

2) 当普通分配失败时,新的处理程序将投入其储备

3) 控制负载管理的代码可以钩住内存管理系统,并确定它何时已进入其保留空间。它的反应通常是修剪缓存和卸载

4) 内存管理器尝试在释放内存时重新填充其储备

5) 恢复保留后,钩子会收到通知,它们可能会增长缓存和/或继续接受额外负载

6) 当储备变低时,可能失败的分配(通常是大型分配)就会失败。所有代码都必须理智地处理大型分配的失败

7) 如果储备耗尽,则无法失败的分配(通常是小分配)将被阻塞


8) 如果阻塞条件持续存在,或者大量分配继续失败,并且无法恢复保留,则会触发异常终止。

它可以丢弃实际不需要的数据。比如说,photoshop以多种比例缓存显示图像,并尽可能多地保存。这就是它如何知道它能逃脱多少惩罚。

不返回 它只是尽其所能,但未能提供更多的内存。它调用
exit()
abort()
并终止进程

这可以用作快速故障策略。如果系统内存不足,并且已知某些进程不需要(例如:童工),则调用
abort()
将为其他进程释放内存,这是摆脱进程的最快方法

抛出异常 抛出
bad_alloc
意味着分配器无法释放任何内存,并且应用程序是否可以通过某种方式恢复。我个人并不在乎是否真的抓到了
bad\u alloc
,因为这不应该发生,或者我对此无能为力

如果您使用的是在内存耗尽时返回
nullptr
以强制抛出的古老编译器,则可以使用此选项。不过,这是否有效还值得怀疑

卸载新的处理程序 查看书籍调用
set\u new\u处理程序(nullptr)应卸载新处理程序。根据Scott Meyer的说法,这将导致
操作员new
抛出
错误分配
异常。这应该与您自己抛出异常相同

安装不同的新处理程序 由于在解决分配错误之前调用
new\u处理程序
(即,
operator new
)如果提供的实现
new\u处理程序
无法解决问题,则应将条件传播到另一层

如果我自己安装一个
new\u处理程序
,我会保留一个对以前的
new\u处理程序
的引用(另请参见:),以便在我的算法失败时将其替换回来

使更多的内存可用 这里的假设是应用程序安装了
新的\u处理程序本身。
new_handler
的作者在此有机会反思或修改分配的内存。因此,程序员安装了
新的\u处理程序
,因为他知道有一些内存需要释放。如果一切都出了问题,有一个从失败中恢复过来的策略

可能发生的事情的不完整列表(部分猜测):

  • 您的操作系统允许您手动调用内存不足杀手(以释放内存)
  • 如果您使用的是Boehm垃圾收集器,那么实际上可以调用
    GC\u gcollect()强制垃圾收集
  • 您自己已经保留了一些内存,现在就开始使用
  • 您可以手动调用delete来删除已知的昂贵的不重要对象(缓存)
  • 您有一个像Perl、Python或Mono一样运行的解释器,并调用它的垃圾收集器告诉他们您的内存不足(或者他们自己在
    init()
    例程上安装新的处理程序)
实施 下面是实现