了解新处理程序的行为
Understand the behavior of the new-handler
我正在阅读Scott Meyers的《有效的C++55》,有一个来自第49项的问题:
当operator new
无法满足内存请求时,它调用新的处理程序函数重复执行,直到找到足够的内存为止。
一个设计良好的newhandler函数必须执行以下操作之一:
- 释放更多可用内存
- 安装不同的新处理程序
- 卸载新处理程序
- 引发异常
- 不返回
当new
无法分配内存时,意味着内存不足,问题是newhandler如何以及从哪里分配更多内存?
你能解释一下所有这些步骤吗?
这取决于实现。我可以告诉你我通常的做法:
1) 新的处理程序在启动时分配大量内存作为保留。
2) 当普通分配失败时,新的处理程序会动用其储备。
3) 控制负载管理的代码可以挂接内存管理系统,并确定它何时已进入其保留区。它通常通过修剪缓存和减少负载来做出反应。
4) 内存管理器试图在释放内存时重新填充其保留空间。
5) 当保留被恢复时,钩子会被通知它们可能会增长缓存和/或恢复接受额外的负载。
6) 当储备变低时,可能失败的分配(通常是大额分配)就会失败。所有代码都必须理智地处理大型分配的失败。
7) 如果储备耗尽,无法失败的分配(通常是小的分配)就会阻塞。
8) 如果阻塞情况持续存在,或者大量分配继续失败,并且保留无法恢复,则会触发异常终止。
它可以丢弃并非真正需要的数据。比如说,photoshop以几个比例缓存显示图像,并尽可能多地保存。这就是它知道自己能逃脱多少惩罚的方式。
不返回
它只是尽其所能,但未能提供更多可用内存。它调用exit()
或abort()
并终止进程。
这可以用作快速失效策略。如果系统内存不足,并且已知不需要某些进程(例如:子进程),则调用abort()
将为其他进程释放内存,这是摆脱进程的最快方法。
引发异常
抛出bad_alloc
意味着分配器无法释放任何内存,并且应用程序是否可以通过某种方式恢复。我个人不在乎实际捕获bad_alloc
,因为它不应该发生,或者我对此无能为力。
如果您使用的是在内存不足时返回nullptr
以强制它们抛出的古代编译器,则可以使用此方法。不过,这是否可行还值得怀疑。
卸载新处理程序
查看调用set_new_handler(nullptr);
的书应该会卸载新的处理程序。根据Scott Meyer的说法,这应该会导致operator new
抛出bad_alloc
异常。这应该与您自己抛出异常相同。
安装不同的新处理程序
由于new_handler
被调用,直到分配错误得到解决(即:operator new
没有解决),如果new_handler
提供的实现不能解决问题,则它应该将条件传播到另一层。
如果我自己安装new_handler
,我会保留对以前的new_handler
的引用(另请参见:get_new_handler()
),以便在我的算法失败时将其交换回来。
释放更多可用内存
这里的假设是应用程序本身安装了new_handler
。new_handler
的作者在这里有机会反思或修改分配的内存。所以程序员安装了new_handler
,因为他知道有一些内存可以释放。如果一切都出了问题,有一个策略可以从这次失败中恢复过来。
可能发生的事情的不完整列表(部分猜测):
- 您的操作系统允许您手动调用内存不足杀手(以释放内存)
- 如果您正在使用Boehm垃圾收集器,那么实际上可以调用
GC_gcollect();
来强制进行垃圾收集 - 你自己保留了一些内存,现在就开始使用
- 您可以手动调用delete来删除已知的可开销的不重要对象(缓存)
- 你有一个像Perl、Python或Mono一样运行的解释器,并调用它的垃圾收集器来告诉他们你的内存不足(或者他们自己在
init()
例程上安装新的处理程序)
实施
以下是libstdc++的实现。
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 为什么我的 IExtractIcon 处理程序没有被调用?
- 在遍历处理程序的向量时注册和注销处理程序
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 在C++程序中使用的迭代器中未处理的异常
- 有关图像处理应用程序的硬件和软件安全性的建议
- 通过安装信号处理程序关闭多线程应用程序
- QDateTime::toString() 在退出处理程序中使用时失败
- 如何在 WindowProc 处理程序中区分箭头键和数字键盘?
- async_write完成处理程序最早何时完成?
- C++事件系统 - 多态事件和事件处理程序
- 使用信号处理程序处理从 FIFO 接收的数据
- 使用独立的 c++ 程序处理用 C 编写的字符设备驱动程序
- C 程序处理两个文件,而不是一个文件
- 是什么让这个程序处理缓慢?(C++)
- QT 中的应用程序>处理消息?
- MongoDB C++驱动程序处理副本集连接故障
- 使用 OpenCV 程序处理多页 PDF