了解新处理程序的行为 我正在阅读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()
例程上安装新的处理程序)
实施
下面是实现